1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions
6 // are met:
7 //
8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // - Redistribution in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the
14 // distribution.
15 //
16 // - Neither the name of Sun Microsystems or the names of contributors may
17 // be used to endorse or promote products derived from this software without
18 // specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 // OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 // The original source code covered by the above license above has been
34 // modified significantly by Google Inc.
35 // Copyright 2012 the V8 project authors. All rights reserved.
36 
37 #include "src/arm/assembler-arm.h"
38 
39 #if V8_TARGET_ARCH_ARM
40 
41 #include "src/arm/assembler-arm-inl.h"
42 #include "src/base/bits.h"
43 #include "src/base/cpu.h"
44 #include "src/macro-assembler.h"
45 
46 namespace v8 {
47 namespace internal {
48 
49 // 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.
CpuFeaturesImpliedByCompiler()53 static 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 
ProbeImpl(bool cross_compile)83 void CpuFeatures::ProbeImpl(bool cross_compile) {
84   supported_ |= CpuFeaturesImpliedByCompiler();
85   cache_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     cache_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 
PrintTarget()156 void 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 
PrintFeatures()210 void 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
239 const int RelocInfo::kApplyMask = 0;
240 
241 
IsCodedSpecially()242 bool 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 
IsInConstantPool()251 bool 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 
Operand(Handle<Object> handle)260 Operand::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 
Operand(Register rm,ShiftOp shift_op,int shift_imm)277 Operand::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 
Operand(Register rm,ShiftOp shift_op,Register rs)298 Operand::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 
MemOperand(Register rn,int32_t offset,AddrMode am)307 MemOperand::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 
MemOperand(Register rn,Register rm,AddrMode am)322 MemOperand::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 
MemOperand(Register rn,Register rm,ShiftOp shift_op,int shift_imm,AddrMode am)331 MemOperand::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 
NeonMemOperand(Register rn,AddrMode am,int align)342 NeonMemOperand::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 
NeonMemOperand(Register rn,Register rm,int align)350 NeonMemOperand::NeonMemOperand(Register rn, Register rm, int align) {
351   rn_ = rn;
352   rm_ = rm;
353   SetAlignment(align);
354 }
355 
356 
SetAlignment(int align)357 void 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 
NeonListOperand(DoubleRegister base,int registers_count)379 NeonListOperand::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.
407 const 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.
411 const Instr kPopRegPattern =
412     al | B26 | L | 4 | PostIndex | Register::kCode_sp * B16;
413 // ldr rd, [pc, #offset]
414 const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
415 const Instr kLdrPCImmedPattern = 5 * B24 | L | Register::kCode_pc * B16;
416 // ldr rd, [pp, #offset]
417 const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
418 const Instr kLdrPpImmedPattern = 5 * B24 | L | Register::kCode_r8 * B16;
419 // ldr rd, [pp, rn]
420 const Instr kLdrPpRegMask = 15 * B24 | 7 * B20 | 15 * B16;
421 const Instr kLdrPpRegPattern = 7 * B24 | L | Register::kCode_r8 * B16;
422 // vldr dd, [pc, #offset]
423 const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
424 const Instr kVldrDPCPattern = 13 * B24 | L | Register::kCode_pc * B16 | 11 * B8;
425 // vldr dd, [pp, #offset]
426 const Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
427 const Instr kVldrDPpPattern = 13 * B24 | L | Register::kCode_r8 * B16 | 11 * B8;
428 // blxcc rm
429 const Instr kBlxRegMask =
430     15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
431 const Instr kBlxRegPattern =
432     B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | BLX;
433 const Instr kBlxIp = al | kBlxRegPattern | ip.code();
434 const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16;
435 const Instr kMovMvnPattern = 0xd * B21;
436 const Instr kMovMvnFlip = B22;
437 const Instr kMovLeaveCCMask = 0xdff * B16;
438 const Instr kMovLeaveCCPattern = 0x1a0 * B16;
439 const Instr kMovwPattern = 0x30 * B20;
440 const Instr kMovtPattern = 0x34 * B20;
441 const Instr kMovwLeaveCCFlip = 0x5 * B21;
442 const Instr kMovImmedMask = 0x7f * B21;
443 const Instr kMovImmedPattern = 0x1d * B21;
444 const Instr kOrrImmedMask = 0x7f * B21;
445 const Instr kOrrImmedPattern = 0x1c * B21;
446 const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
447 const Instr kCmpCmnPattern = 0x15 * B20;
448 const Instr kCmpCmnFlip = B21;
449 const Instr kAddSubFlip = 0x6 * B21;
450 const Instr kAndBicFlip = 0xe * B21;
451 
452 // A mask for the Rd register for push, pop, ldr, str instructions.
453 const Instr kLdrRegFpOffsetPattern =
454     al | B26 | L | Offset | Register::kCode_fp * B16;
455 const Instr kStrRegFpOffsetPattern =
456     al | B26 | Offset | Register::kCode_fp * B16;
457 const Instr kLdrRegFpNegOffsetPattern =
458     al | B26 | L | NegOffset | Register::kCode_fp * B16;
459 const Instr kStrRegFpNegOffsetPattern =
460     al | B26 | NegOffset | Register::kCode_fp * B16;
461 const Instr kLdrStrInstrTypeMask = 0xffff0000;
462 
463 
Assembler(Isolate * isolate,void * buffer,int buffer_size)464 Assembler::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 
~Assembler()484 Assembler::~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 
GetCode(CodeDesc * desc)495 void 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 
Align(int m)518 void 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 
CodeTargetAlign()527 void Assembler::CodeTargetAlign() {
528   // Preferred alignment of jump targets on some ARM chips.
529   Align(8);
530 }
531 
532 
GetCondition(Instr instr)533 Condition Assembler::GetCondition(Instr instr) {
534   return Instruction::ConditionField(instr);
535 }
536 
537 
IsBranch(Instr instr)538 bool Assembler::IsBranch(Instr instr) {
539   return (instr & (B27 | B25)) == (B27 | B25);
540 }
541 
542 
GetBranchOffset(Instr instr)543 int 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 
IsLdrRegisterImmediate(Instr instr)551 bool Assembler::IsLdrRegisterImmediate(Instr instr) {
552   return (instr & (B27 | B26 | B25 | B22 | B20)) == (B26 | B20);
553 }
554 
555 
IsVldrDRegisterImmediate(Instr instr)556 bool Assembler::IsVldrDRegisterImmediate(Instr instr) {
557   return (instr & (15 * B24 | 3 * B20 | 15 * B8)) == (13 * B24 | B20 | 11 * B8);
558 }
559 
560 
GetLdrRegisterImmediateOffset(Instr instr)561 int 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 
GetVldrDRegisterImmediateOffset(Instr instr)569 int 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 
SetLdrRegisterImmediateOffset(Instr instr,int offset)578 Instr 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 
SetVldrDRegisterImmediateOffset(Instr instr,int offset)590 Instr 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 
IsStrRegisterImmediate(Instr instr)603 bool Assembler::IsStrRegisterImmediate(Instr instr) {
604   return (instr & (B27 | B26 | B25 | B22 | B20)) == B26;
605 }
606 
607 
SetStrRegisterImmediateOffset(Instr instr,int offset)608 Instr 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 
IsAddRegisterImmediate(Instr instr)620 bool Assembler::IsAddRegisterImmediate(Instr instr) {
621   return (instr & (B27 | B26 | B25 | B24 | B23 | B22 | B21)) == (B25 | B23);
622 }
623 
624 
SetAddRegisterImmediateOffset(Instr instr,int offset)625 Instr 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 
GetRd(Instr instr)634 Register Assembler::GetRd(Instr instr) {
635   Register reg;
636   reg.reg_code = Instruction::RdValue(instr);
637   return reg;
638 }
639 
640 
GetRn(Instr instr)641 Register Assembler::GetRn(Instr instr) {
642   Register reg;
643   reg.reg_code = Instruction::RnValue(instr);
644   return reg;
645 }
646 
647 
GetRm(Instr instr)648 Register Assembler::GetRm(Instr instr) {
649   Register reg;
650   reg.reg_code = Instruction::RmValue(instr);
651   return reg;
652 }
653 
654 
GetConsantPoolLoadPattern()655 Instr Assembler::GetConsantPoolLoadPattern() {
656   if (FLAG_enable_embedded_constant_pool) {
657     return kLdrPpImmedPattern;
658   } else {
659     return kLdrPCImmedPattern;
660   }
661 }
662 
663 
GetConsantPoolLoadMask()664 Instr Assembler::GetConsantPoolLoadMask() {
665   if (FLAG_enable_embedded_constant_pool) {
666     return kLdrPpImmedMask;
667   } else {
668     return kLdrPCImmedMask;
669   }
670 }
671 
672 
IsPush(Instr instr)673 bool Assembler::IsPush(Instr instr) {
674   return ((instr & ~kRdMask) == kPushRegPattern);
675 }
676 
677 
IsPop(Instr instr)678 bool Assembler::IsPop(Instr instr) {
679   return ((instr & ~kRdMask) == kPopRegPattern);
680 }
681 
682 
IsStrRegFpOffset(Instr instr)683 bool Assembler::IsStrRegFpOffset(Instr instr) {
684   return ((instr & kLdrStrInstrTypeMask) == kStrRegFpOffsetPattern);
685 }
686 
687 
IsLdrRegFpOffset(Instr instr)688 bool Assembler::IsLdrRegFpOffset(Instr instr) {
689   return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpOffsetPattern);
690 }
691 
692 
IsStrRegFpNegOffset(Instr instr)693 bool Assembler::IsStrRegFpNegOffset(Instr instr) {
694   return ((instr & kLdrStrInstrTypeMask) == kStrRegFpNegOffsetPattern);
695 }
696 
697 
IsLdrRegFpNegOffset(Instr instr)698 bool Assembler::IsLdrRegFpNegOffset(Instr instr) {
699   return ((instr & kLdrStrInstrTypeMask) == kLdrRegFpNegOffsetPattern);
700 }
701 
702 
IsLdrPcImmediateOffset(Instr instr)703 bool 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 
IsLdrPpImmediateOffset(Instr instr)710 bool 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 
IsLdrPpRegOffset(Instr instr)717 bool 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 
GetLdrPpRegOffsetPattern()724 Instr Assembler::GetLdrPpRegOffsetPattern() { return kLdrPpRegPattern; }
725 
726 
IsVldrDPcImmediateOffset(Instr instr)727 bool 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 
IsVldrDPpImmediateOffset(Instr instr)734 bool 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 
IsBlxReg(Instr instr)741 bool Assembler::IsBlxReg(Instr instr) {
742   // Check the instruction is indeed a
743   // blxcc <Rm>
744   return (instr & kBlxRegMask) == kBlxRegPattern;
745 }
746 
747 
IsBlxIp(Instr instr)748 bool Assembler::IsBlxIp(Instr instr) {
749   // Check the instruction is indeed a
750   // blx ip
751   return instr == kBlxIp;
752 }
753 
754 
IsTstImmediate(Instr instr)755 bool Assembler::IsTstImmediate(Instr instr) {
756   return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
757       (I | TST | S);
758 }
759 
760 
IsCmpRegister(Instr instr)761 bool Assembler::IsCmpRegister(Instr instr) {
762   return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask | B4)) ==
763       (CMP | S);
764 }
765 
766 
IsCmpImmediate(Instr instr)767 bool Assembler::IsCmpImmediate(Instr instr) {
768   return (instr & (B27 | B26 | I | kOpCodeMask | S | kRdMask)) ==
769       (I | CMP | S);
770 }
771 
772 
GetCmpImmediateRegister(Instr instr)773 Register Assembler::GetCmpImmediateRegister(Instr instr) {
774   DCHECK(IsCmpImmediate(instr));
775   return GetRn(instr);
776 }
777 
778 
GetCmpImmediateRawImmediate(Instr instr)779 int 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 
target_at(int pos)803 int 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 
target_at_put(int pos,int target_pos)820 void 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 
print(Label * L)901 void 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 
bind_to(Label * L,int pos)959 void 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 
bind(Label * L)975 void Assembler::bind(Label* L) {
976   DCHECK(!L->is_bound());  // label can only be bound once
977   bind_to(L, pc_offset());
978 }
979 
980 
next(Label * L)981 void 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!
fits_shifter(uint32_t imm32,uint32_t * rotate_imm,uint32_t * immed_8,Instr * instr)999 static 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.
must_output_reloc_info(const Assembler * assembler) const1059 bool 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 
use_mov_immediate_load(const Operand & x,const Assembler * assembler)1070 static 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 
instructions_required(const Assembler * assembler,Instr instr) const1089 int 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 
move_32_bit_immediate(Register rd,const Operand & x,Condition cond)1126 void 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 
addrmod1(Instr instr,Register rn,Register rd,const Operand & x)1182 void 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 
addrmod2(Instr instr,Register rd,const MemOperand & x)1225 void 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 
addrmod3(Instr instr,Register rd,const MemOperand & x)1257 void 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 
addrmod4(Instr instr,Register rn,RegList rl)1296 void 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 
addrmod5(Instr instr,CRegister crd,const MemOperand & x)1304 void 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 
branch_offset(Label * L)1329 int 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.
b(int branch_offset,Condition cond)1353 void 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 
bl(int branch_offset,Condition cond)1366 void 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 
blx(int branch_offset)1375 void 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 
blx(Register target,Condition cond)1385 void 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 
bx(Register target,Condition cond)1392 void 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 
b(Label * L,Condition cond)1399 void Assembler::b(Label* L, Condition cond) {
1400   CheckBuffer();
1401   b(branch_offset(L), cond);
1402 }
1403 
1404 
bl(Label * L,Condition cond)1405 void Assembler::bl(Label* L, Condition cond) {
1406   CheckBuffer();
1407   bl(branch_offset(L), cond);
1408 }
1409 
1410 
blx(Label * L)1411 void Assembler::blx(Label* L) {
1412   CheckBuffer();
1413   blx(branch_offset(L));
1414 }
1415 
1416 
1417 // Data-processing instructions.
1418 
and_(Register dst,Register src1,const Operand & src2,SBit s,Condition cond)1419 void 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 
eor(Register dst,Register src1,const Operand & src2,SBit s,Condition cond)1425 void 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 
sub(Register dst,Register src1,const Operand & src2,SBit s,Condition cond)1431 void 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 
rsb(Register dst,Register src1,const Operand & src2,SBit s,Condition cond)1437 void 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 
add(Register dst,Register src1,const Operand & src2,SBit s,Condition cond)1443 void 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 
adc(Register dst,Register src1,const Operand & src2,SBit s,Condition cond)1449 void 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 
sbc(Register dst,Register src1,const Operand & src2,SBit s,Condition cond)1455 void 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 
rsc(Register dst,Register src1,const Operand & src2,SBit s,Condition cond)1461 void 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 
tst(Register src1,const Operand & src2,Condition cond)1467 void Assembler::tst(Register src1, const Operand& src2, Condition cond) {
1468   addrmod1(cond | TST | S, src1, r0, src2);
1469 }
1470 
1471 
teq(Register src1,const Operand & src2,Condition cond)1472 void Assembler::teq(Register src1, const Operand& src2, Condition cond) {
1473   addrmod1(cond | TEQ | S, src1, r0, src2);
1474 }
1475 
1476 
cmp(Register src1,const Operand & src2,Condition cond)1477 void Assembler::cmp(Register src1, const Operand& src2, Condition cond) {
1478   addrmod1(cond | CMP | S, src1, r0, src2);
1479 }
1480 
1481 
cmp_raw_immediate(Register src,int raw_immediate,Condition cond)1482 void 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 
cmn(Register src1,const Operand & src2,Condition cond)1489 void Assembler::cmn(Register src1, const Operand& src2, Condition cond) {
1490   addrmod1(cond | CMN | S, src1, r0, src2);
1491 }
1492 
1493 
orr(Register dst,Register src1,const Operand & src2,SBit s,Condition cond)1494 void 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 
mov(Register dst,const Operand & src,SBit s,Condition cond)1500 void 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 
mov_label_offset(Register dst,Label * label)1512 void 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 
movw(Register reg,uint32_t immediate,Condition cond)1551 void 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 
movt(Register reg,uint32_t immediate,Condition cond)1557 void 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 
bic(Register dst,Register src1,const Operand & src2,SBit s,Condition cond)1563 void 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 
mvn(Register dst,const Operand & src,SBit s,Condition cond)1569 void 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.
mla(Register dst,Register src1,Register src2,Register srcA,SBit s,Condition cond)1575 void 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 
mls(Register dst,Register src1,Register src2,Register srcA,Condition cond)1583 void 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 
sdiv(Register dst,Register src1,Register src2,Condition cond)1592 void 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 
udiv(Register dst,Register src1,Register src2,Condition cond)1601 void 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 
mul(Register dst,Register src1,Register src2,SBit s,Condition cond)1610 void 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 
smmla(Register dst,Register src1,Register src2,Register srcA,Condition cond)1618 void 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 
smmul(Register dst,Register src1,Register src2,Condition cond)1626 void 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 
smlal(Register dstL,Register dstH,Register src1,Register src2,SBit s,Condition cond)1634 void 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 
smull(Register dstL,Register dstH,Register src1,Register src2,SBit s,Condition cond)1647 void 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 
umlal(Register dstL,Register dstH,Register src1,Register src2,SBit s,Condition cond)1660 void 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 
umull(Register dstL,Register dstH,Register src1,Register src2,SBit s,Condition cond)1673 void 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.
clz(Register dst,Register src,Condition cond)1687 void 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.
usat(Register dst,int satpos,const Operand & src,Condition cond)1698 void 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
ubfx(Register dst,Register src,int lsb,int width,Condition cond)1725 void 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
sbfx(Register dst,Register src,int lsb,int width,Condition cond)1745 void 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
bfc(Register dst,int lsb,int width,Condition cond)1764 void 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
bfi(Register dst,Register src,int lsb,int width,Condition cond)1779 void 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 
pkhbt(Register dst,Register src1,const Operand & src2,Condition cond)1795 void 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 
pkhtb(Register dst,Register src1,const Operand & src2,Condition cond)1814 void 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 
sxtb(Register dst,Register src,int rotate,Condition cond)1834 void 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 
sxtab(Register dst,Register src1,Register src2,int rotate,Condition cond)1846 void 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 
sxth(Register dst,Register src,int rotate,Condition cond)1860 void 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 
sxtah(Register dst,Register src1,Register src2,int rotate,Condition cond)1872 void 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 
uxtb(Register dst,Register src,int rotate,Condition cond)1886 void 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 
uxtab(Register dst,Register src1,Register src2,int rotate,Condition cond)1898 void 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 
uxtb16(Register dst,Register src,int rotate,Condition cond)1912 void 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 
uxth(Register dst,Register src,int rotate,Condition cond)1924 void 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 
uxtah(Register dst,Register src1,Register src2,int rotate,Condition cond)1936 void 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 
1950 // Status register access instructions.
mrs(Register dst,SRegister s,Condition cond)1951 void Assembler::mrs(Register dst, SRegister s, Condition cond) {
1952   DCHECK(!dst.is(pc));
1953   emit(cond | B24 | s | 15*B16 | dst.code()*B12);
1954 }
1955 
1956 
msr(SRegisterFieldMask fields,const Operand & src,Condition cond)1957 void Assembler::msr(SRegisterFieldMask fields, const Operand& src,
1958                     Condition cond) {
1959   DCHECK(fields >= B16 && fields < B20);  // at least one field set
1960   Instr instr;
1961   if (!src.rm_.is_valid()) {
1962     // Immediate.
1963     uint32_t rotate_imm;
1964     uint32_t immed_8;
1965     if (src.must_output_reloc_info(this) ||
1966         !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
1967       // Immediate operand cannot be encoded, load it first to register ip.
1968       move_32_bit_immediate(ip, src);
1969       msr(fields, Operand(ip), cond);
1970       return;
1971     }
1972     instr = I | rotate_imm*B8 | immed_8;
1973   } else {
1974     DCHECK(!src.rs_.is_valid() && src.shift_imm_ == 0);  // only rm allowed
1975     instr = src.rm_.code();
1976   }
1977   emit(cond | instr | B24 | B21 | fields | 15*B12);
1978 }
1979 
1980 
1981 // Load/Store instructions.
ldr(Register dst,const MemOperand & src,Condition cond)1982 void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
1983   if (dst.is(pc)) {
1984     positions_recorder()->WriteRecordedPositions();
1985   }
1986   addrmod2(cond | B26 | L, dst, src);
1987 }
1988 
1989 
str(Register src,const MemOperand & dst,Condition cond)1990 void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
1991   addrmod2(cond | B26, src, dst);
1992 }
1993 
1994 
ldrb(Register dst,const MemOperand & src,Condition cond)1995 void Assembler::ldrb(Register dst, const MemOperand& src, Condition cond) {
1996   addrmod2(cond | B26 | B | L, dst, src);
1997 }
1998 
1999 
strb(Register src,const MemOperand & dst,Condition cond)2000 void Assembler::strb(Register src, const MemOperand& dst, Condition cond) {
2001   addrmod2(cond | B26 | B, src, dst);
2002 }
2003 
2004 
ldrh(Register dst,const MemOperand & src,Condition cond)2005 void Assembler::ldrh(Register dst, const MemOperand& src, Condition cond) {
2006   addrmod3(cond | L | B7 | H | B4, dst, src);
2007 }
2008 
2009 
strh(Register src,const MemOperand & dst,Condition cond)2010 void Assembler::strh(Register src, const MemOperand& dst, Condition cond) {
2011   addrmod3(cond | B7 | H | B4, src, dst);
2012 }
2013 
2014 
ldrsb(Register dst,const MemOperand & src,Condition cond)2015 void Assembler::ldrsb(Register dst, const MemOperand& src, Condition cond) {
2016   addrmod3(cond | L | B7 | S6 | B4, dst, src);
2017 }
2018 
2019 
ldrsh(Register dst,const MemOperand & src,Condition cond)2020 void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
2021   addrmod3(cond | L | B7 | S6 | H | B4, dst, src);
2022 }
2023 
2024 
ldrd(Register dst1,Register dst2,const MemOperand & src,Condition cond)2025 void Assembler::ldrd(Register dst1, Register dst2,
2026                      const MemOperand& src, Condition cond) {
2027   DCHECK(IsEnabled(ARMv7));
2028   DCHECK(src.rm().is(no_reg));
2029   DCHECK(!dst1.is(lr));  // r14.
2030   DCHECK_EQ(0, dst1.code() % 2);
2031   DCHECK_EQ(dst1.code() + 1, dst2.code());
2032   addrmod3(cond | B7 | B6 | B4, dst1, src);
2033 }
2034 
2035 
strd(Register src1,Register src2,const MemOperand & dst,Condition cond)2036 void Assembler::strd(Register src1, Register src2,
2037                      const MemOperand& dst, Condition cond) {
2038   DCHECK(dst.rm().is(no_reg));
2039   DCHECK(!src1.is(lr));  // r14.
2040   DCHECK_EQ(0, src1.code() % 2);
2041   DCHECK_EQ(src1.code() + 1, src2.code());
2042   DCHECK(IsEnabled(ARMv7));
2043   addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
2044 }
2045 
2046 
2047 // Preload instructions.
pld(const MemOperand & address)2048 void Assembler::pld(const MemOperand& address) {
2049   // Instruction details available in ARM DDI 0406C.b, A8.8.128.
2050   // 1111(31-28) | 0111(27-24) | U(23) | R(22) | 01(21-20) | Rn(19-16) |
2051   // 1111(15-12) | imm5(11-07) | type(6-5) | 0(4)| Rm(3-0) |
2052   DCHECK(address.rm().is(no_reg));
2053   DCHECK(address.am() == Offset);
2054   int U = B23;
2055   int offset = address.offset();
2056   if (offset < 0) {
2057     offset = -offset;
2058     U = 0;
2059   }
2060   DCHECK(offset < 4096);
2061   emit(kSpecialCondition | B26 | B24 | U | B22 | B20 | address.rn().code()*B16 |
2062        0xf*B12 | offset);
2063 }
2064 
2065 
2066 // Load/Store multiple instructions.
ldm(BlockAddrMode am,Register base,RegList dst,Condition cond)2067 void Assembler::ldm(BlockAddrMode am,
2068                     Register base,
2069                     RegList dst,
2070                     Condition cond) {
2071   // ABI stack constraint: ldmxx base, {..sp..}  base != sp  is not restartable.
2072   DCHECK(base.is(sp) || (dst & sp.bit()) == 0);
2073 
2074   addrmod4(cond | B27 | am | L, base, dst);
2075 
2076   // Emit the constant pool after a function return implemented by ldm ..{..pc}.
2077   if (cond == al && (dst & pc.bit()) != 0) {
2078     // There is a slight chance that the ldm instruction was actually a call,
2079     // in which case it would be wrong to return into the constant pool; we
2080     // recognize this case by checking if the emission of the pool was blocked
2081     // at the pc of the ldm instruction by a mov lr, pc instruction; if this is
2082     // the case, we emit a jump over the pool.
2083     CheckConstPool(true, no_const_pool_before_ == pc_offset() - kInstrSize);
2084   }
2085 }
2086 
2087 
stm(BlockAddrMode am,Register base,RegList src,Condition cond)2088 void Assembler::stm(BlockAddrMode am,
2089                     Register base,
2090                     RegList src,
2091                     Condition cond) {
2092   addrmod4(cond | B27 | am, base, src);
2093 }
2094 
2095 
2096 // Exception-generating instructions and debugging support.
2097 // Stops with a non-negative code less than kNumOfWatchedStops support
2098 // enabling/disabling and a counter feature. See simulator-arm.h .
stop(const char * msg,Condition cond,int32_t code)2099 void Assembler::stop(const char* msg, Condition cond, int32_t code) {
2100 #ifndef __arm__
2101   DCHECK(code >= kDefaultStopCode);
2102   {
2103     // The Simulator will handle the stop instruction and get the message
2104     // address. It expects to find the address just after the svc instruction.
2105     BlockConstPoolScope block_const_pool(this);
2106     if (code >= 0) {
2107       svc(kStopCode + code, cond);
2108     } else {
2109       svc(kStopCode + kMaxStopCode, cond);
2110     }
2111     emit(reinterpret_cast<Instr>(msg));
2112   }
2113 #else  // def __arm__
2114   if (cond != al) {
2115     Label skip;
2116     b(&skip, NegateCondition(cond));
2117     bkpt(0);
2118     bind(&skip);
2119   } else {
2120     bkpt(0);
2121   }
2122 #endif  // def __arm__
2123 }
2124 
2125 
bkpt(uint32_t imm16)2126 void Assembler::bkpt(uint32_t imm16) {  // v5 and above
2127   DCHECK(is_uint16(imm16));
2128   emit(al | B24 | B21 | (imm16 >> 4)*B8 | BKPT | (imm16 & 0xf));
2129 }
2130 
2131 
svc(uint32_t imm24,Condition cond)2132 void Assembler::svc(uint32_t imm24, Condition cond) {
2133   DCHECK(is_uint24(imm24));
2134   emit(cond | 15*B24 | imm24);
2135 }
2136 
2137 
2138 // Coprocessor instructions.
cdp(Coprocessor coproc,int opcode_1,CRegister crd,CRegister crn,CRegister crm,int opcode_2,Condition cond)2139 void Assembler::cdp(Coprocessor coproc,
2140                     int opcode_1,
2141                     CRegister crd,
2142                     CRegister crn,
2143                     CRegister crm,
2144                     int opcode_2,
2145                     Condition cond) {
2146   DCHECK(is_uint4(opcode_1) && is_uint3(opcode_2));
2147   emit(cond | B27 | B26 | B25 | (opcode_1 & 15)*B20 | crn.code()*B16 |
2148        crd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | crm.code());
2149 }
2150 
2151 
cdp2(Coprocessor coproc,int opcode_1,CRegister crd,CRegister crn,CRegister crm,int opcode_2)2152 void Assembler::cdp2(Coprocessor coproc,
2153                      int opcode_1,
2154                      CRegister crd,
2155                      CRegister crn,
2156                      CRegister crm,
2157                      int opcode_2) {  // v5 and above
2158   cdp(coproc, opcode_1, crd, crn, crm, opcode_2, kSpecialCondition);
2159 }
2160 
2161 
mcr(Coprocessor coproc,int opcode_1,Register rd,CRegister crn,CRegister crm,int opcode_2,Condition cond)2162 void Assembler::mcr(Coprocessor coproc,
2163                     int opcode_1,
2164                     Register rd,
2165                     CRegister crn,
2166                     CRegister crm,
2167                     int opcode_2,
2168                     Condition cond) {
2169   DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
2170   emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | crn.code()*B16 |
2171        rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
2172 }
2173 
2174 
mcr2(Coprocessor coproc,int opcode_1,Register rd,CRegister crn,CRegister crm,int opcode_2)2175 void Assembler::mcr2(Coprocessor coproc,
2176                      int opcode_1,
2177                      Register rd,
2178                      CRegister crn,
2179                      CRegister crm,
2180                      int opcode_2) {  // v5 and above
2181   mcr(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
2182 }
2183 
2184 
mrc(Coprocessor coproc,int opcode_1,Register rd,CRegister crn,CRegister crm,int opcode_2,Condition cond)2185 void Assembler::mrc(Coprocessor coproc,
2186                     int opcode_1,
2187                     Register rd,
2188                     CRegister crn,
2189                     CRegister crm,
2190                     int opcode_2,
2191                     Condition cond) {
2192   DCHECK(is_uint3(opcode_1) && is_uint3(opcode_2));
2193   emit(cond | B27 | B26 | B25 | (opcode_1 & 7)*B21 | L | crn.code()*B16 |
2194        rd.code()*B12 | coproc*B8 | (opcode_2 & 7)*B5 | B4 | crm.code());
2195 }
2196 
2197 
mrc2(Coprocessor coproc,int opcode_1,Register rd,CRegister crn,CRegister crm,int opcode_2)2198 void Assembler::mrc2(Coprocessor coproc,
2199                      int opcode_1,
2200                      Register rd,
2201                      CRegister crn,
2202                      CRegister crm,
2203                      int opcode_2) {  // v5 and above
2204   mrc(coproc, opcode_1, rd, crn, crm, opcode_2, kSpecialCondition);
2205 }
2206 
2207 
ldc(Coprocessor coproc,CRegister crd,const MemOperand & src,LFlag l,Condition cond)2208 void Assembler::ldc(Coprocessor coproc,
2209                     CRegister crd,
2210                     const MemOperand& src,
2211                     LFlag l,
2212                     Condition cond) {
2213   addrmod5(cond | B27 | B26 | l | L | coproc*B8, crd, src);
2214 }
2215 
2216 
ldc(Coprocessor coproc,CRegister crd,Register rn,int option,LFlag l,Condition cond)2217 void Assembler::ldc(Coprocessor coproc,
2218                     CRegister crd,
2219                     Register rn,
2220                     int option,
2221                     LFlag l,
2222                     Condition cond) {
2223   // Unindexed addressing.
2224   DCHECK(is_uint8(option));
2225   emit(cond | B27 | B26 | U | l | L | rn.code()*B16 | crd.code()*B12 |
2226        coproc*B8 | (option & 255));
2227 }
2228 
2229 
ldc2(Coprocessor coproc,CRegister crd,const MemOperand & src,LFlag l)2230 void Assembler::ldc2(Coprocessor coproc,
2231                      CRegister crd,
2232                      const MemOperand& src,
2233                      LFlag l) {  // v5 and above
2234   ldc(coproc, crd, src, l, kSpecialCondition);
2235 }
2236 
2237 
ldc2(Coprocessor coproc,CRegister crd,Register rn,int option,LFlag l)2238 void Assembler::ldc2(Coprocessor coproc,
2239                      CRegister crd,
2240                      Register rn,
2241                      int option,
2242                      LFlag l) {  // v5 and above
2243   ldc(coproc, crd, rn, option, l, kSpecialCondition);
2244 }
2245 
2246 
2247 // Support for VFP.
2248 
vldr(const DwVfpRegister dst,const Register base,int offset,const Condition cond)2249 void Assembler::vldr(const DwVfpRegister dst,
2250                      const Register base,
2251                      int offset,
2252                      const Condition cond) {
2253   // Ddst = MEM(Rbase + offset).
2254   // Instruction details available in ARM DDI 0406C.b, A8-924.
2255   // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) |
2256   // Vd(15-12) | 1011(11-8) | offset
2257   int u = 1;
2258   if (offset < 0) {
2259     CHECK(offset != kMinInt);
2260     offset = -offset;
2261     u = 0;
2262   }
2263   int vd, d;
2264   dst.split_code(&vd, &d);
2265 
2266   DCHECK(offset >= 0);
2267   if ((offset % 4) == 0 && (offset / 4) < 256) {
2268     emit(cond | 0xD*B24 | u*B23 | d*B22 | B20 | base.code()*B16 | vd*B12 |
2269          0xB*B8 | ((offset / 4) & 255));
2270   } else {
2271     // Larger offsets must be handled by computing the correct address
2272     // in the ip register.
2273     DCHECK(!base.is(ip));
2274     if (u == 1) {
2275       add(ip, base, Operand(offset));
2276     } else {
2277       sub(ip, base, Operand(offset));
2278     }
2279     emit(cond | 0xD*B24 | d*B22 | B20 | ip.code()*B16 | vd*B12 | 0xB*B8);
2280   }
2281 }
2282 
2283 
vldr(const DwVfpRegister dst,const MemOperand & operand,const Condition cond)2284 void Assembler::vldr(const DwVfpRegister dst,
2285                      const MemOperand& operand,
2286                      const Condition cond) {
2287   DCHECK(operand.am_ == Offset);
2288   if (operand.rm().is_valid()) {
2289     add(ip, operand.rn(),
2290         Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2291     vldr(dst, ip, 0, cond);
2292   } else {
2293     vldr(dst, operand.rn(), operand.offset(), cond);
2294   }
2295 }
2296 
2297 
vldr(const SwVfpRegister dst,const Register base,int offset,const Condition cond)2298 void Assembler::vldr(const SwVfpRegister dst,
2299                      const Register base,
2300                      int offset,
2301                      const Condition cond) {
2302   // Sdst = MEM(Rbase + offset).
2303   // Instruction details available in ARM DDI 0406A, A8-628.
2304   // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
2305   // Vdst(15-12) | 1010(11-8) | offset
2306   int u = 1;
2307   if (offset < 0) {
2308     offset = -offset;
2309     u = 0;
2310   }
2311   int sd, d;
2312   dst.split_code(&sd, &d);
2313   DCHECK(offset >= 0);
2314 
2315   if ((offset % 4) == 0 && (offset / 4) < 256) {
2316   emit(cond | u*B23 | d*B22 | 0xD1*B20 | base.code()*B16 | sd*B12 |
2317        0xA*B8 | ((offset / 4) & 255));
2318   } else {
2319     // Larger offsets must be handled by computing the correct address
2320     // in the ip register.
2321     DCHECK(!base.is(ip));
2322     if (u == 1) {
2323       add(ip, base, Operand(offset));
2324     } else {
2325       sub(ip, base, Operand(offset));
2326     }
2327     emit(cond | d*B22 | 0xD1*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
2328   }
2329 }
2330 
2331 
vldr(const SwVfpRegister dst,const MemOperand & operand,const Condition cond)2332 void Assembler::vldr(const SwVfpRegister dst,
2333                      const MemOperand& operand,
2334                      const Condition cond) {
2335   DCHECK(operand.am_ == Offset);
2336   if (operand.rm().is_valid()) {
2337     add(ip, operand.rn(),
2338         Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2339     vldr(dst, ip, 0, cond);
2340   } else {
2341     vldr(dst, operand.rn(), operand.offset(), cond);
2342   }
2343 }
2344 
2345 
vstr(const DwVfpRegister src,const Register base,int offset,const Condition cond)2346 void Assembler::vstr(const DwVfpRegister src,
2347                      const Register base,
2348                      int offset,
2349                      const Condition cond) {
2350   // MEM(Rbase + offset) = Dsrc.
2351   // Instruction details available in ARM DDI 0406C.b, A8-1082.
2352   // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) |
2353   // Vd(15-12) | 1011(11-8) | (offset/4)
2354   int u = 1;
2355   if (offset < 0) {
2356     CHECK(offset != kMinInt);
2357     offset = -offset;
2358     u = 0;
2359   }
2360   DCHECK(offset >= 0);
2361   int vd, d;
2362   src.split_code(&vd, &d);
2363 
2364   if ((offset % 4) == 0 && (offset / 4) < 256) {
2365     emit(cond | 0xD*B24 | u*B23 | d*B22 | base.code()*B16 | vd*B12 | 0xB*B8 |
2366          ((offset / 4) & 255));
2367   } else {
2368     // Larger offsets must be handled by computing the correct address
2369     // in the ip register.
2370     DCHECK(!base.is(ip));
2371     if (u == 1) {
2372       add(ip, base, Operand(offset));
2373     } else {
2374       sub(ip, base, Operand(offset));
2375     }
2376     emit(cond | 0xD*B24 | d*B22 | ip.code()*B16 | vd*B12 | 0xB*B8);
2377   }
2378 }
2379 
2380 
vstr(const DwVfpRegister src,const MemOperand & operand,const Condition cond)2381 void Assembler::vstr(const DwVfpRegister src,
2382                      const MemOperand& operand,
2383                      const Condition cond) {
2384   DCHECK(operand.am_ == Offset);
2385   if (operand.rm().is_valid()) {
2386     add(ip, operand.rn(),
2387         Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2388     vstr(src, ip, 0, cond);
2389   } else {
2390     vstr(src, operand.rn(), operand.offset(), cond);
2391   }
2392 }
2393 
2394 
vstr(const SwVfpRegister src,const Register base,int offset,const Condition cond)2395 void Assembler::vstr(const SwVfpRegister src,
2396                      const Register base,
2397                      int offset,
2398                      const Condition cond) {
2399   // MEM(Rbase + offset) = SSrc.
2400   // Instruction details available in ARM DDI 0406A, A8-786.
2401   // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
2402   // Vdst(15-12) | 1010(11-8) | (offset/4)
2403   int u = 1;
2404   if (offset < 0) {
2405     CHECK(offset != kMinInt);
2406     offset = -offset;
2407     u = 0;
2408   }
2409   int sd, d;
2410   src.split_code(&sd, &d);
2411   DCHECK(offset >= 0);
2412   if ((offset % 4) == 0 && (offset / 4) < 256) {
2413     emit(cond | u*B23 | d*B22 | 0xD0*B20 | base.code()*B16 | sd*B12 |
2414          0xA*B8 | ((offset / 4) & 255));
2415   } else {
2416     // Larger offsets must be handled by computing the correct address
2417     // in the ip register.
2418     DCHECK(!base.is(ip));
2419     if (u == 1) {
2420       add(ip, base, Operand(offset));
2421     } else {
2422       sub(ip, base, Operand(offset));
2423     }
2424     emit(cond | d*B22 | 0xD0*B20 | ip.code()*B16 | sd*B12 | 0xA*B8);
2425   }
2426 }
2427 
2428 
vstr(const SwVfpRegister src,const MemOperand & operand,const Condition cond)2429 void Assembler::vstr(const SwVfpRegister src,
2430                      const MemOperand& operand,
2431                      const Condition cond) {
2432   DCHECK(operand.am_ == Offset);
2433   if (operand.rm().is_valid()) {
2434     add(ip, operand.rn(),
2435         Operand(operand.rm(), operand.shift_op_, operand.shift_imm_));
2436     vstr(src, ip, 0, cond);
2437   } else {
2438     vstr(src, operand.rn(), operand.offset(), cond);
2439   }
2440 }
2441 
2442 
vldm(BlockAddrMode am,Register base,DwVfpRegister first,DwVfpRegister last,Condition cond)2443 void  Assembler::vldm(BlockAddrMode am,
2444                       Register base,
2445                       DwVfpRegister first,
2446                       DwVfpRegister last,
2447                       Condition cond) {
2448   // Instruction details available in ARM DDI 0406C.b, A8-922.
2449   // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
2450   // first(15-12) | 1011(11-8) | (count * 2)
2451   DCHECK_LE(first.code(), last.code());
2452   DCHECK(am == ia || am == ia_w || am == db_w);
2453   DCHECK(!base.is(pc));
2454 
2455   int sd, d;
2456   first.split_code(&sd, &d);
2457   int count = last.code() - first.code() + 1;
2458   DCHECK(count <= 16);
2459   emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
2460        0xB*B8 | count*2);
2461 }
2462 
2463 
vstm(BlockAddrMode am,Register base,DwVfpRegister first,DwVfpRegister last,Condition cond)2464 void  Assembler::vstm(BlockAddrMode am,
2465                       Register base,
2466                       DwVfpRegister first,
2467                       DwVfpRegister last,
2468                       Condition cond) {
2469   // Instruction details available in ARM DDI 0406C.b, A8-1080.
2470   // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
2471   // first(15-12) | 1011(11-8) | (count * 2)
2472   DCHECK_LE(first.code(), last.code());
2473   DCHECK(am == ia || am == ia_w || am == db_w);
2474   DCHECK(!base.is(pc));
2475 
2476   int sd, d;
2477   first.split_code(&sd, &d);
2478   int count = last.code() - first.code() + 1;
2479   DCHECK(count <= 16);
2480   emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
2481        0xB*B8 | count*2);
2482 }
2483 
vldm(BlockAddrMode am,Register base,SwVfpRegister first,SwVfpRegister last,Condition cond)2484 void  Assembler::vldm(BlockAddrMode am,
2485                       Register base,
2486                       SwVfpRegister first,
2487                       SwVfpRegister last,
2488                       Condition cond) {
2489   // Instruction details available in ARM DDI 0406A, A8-626.
2490   // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
2491   // first(15-12) | 1010(11-8) | (count/2)
2492   DCHECK_LE(first.code(), last.code());
2493   DCHECK(am == ia || am == ia_w || am == db_w);
2494   DCHECK(!base.is(pc));
2495 
2496   int sd, d;
2497   first.split_code(&sd, &d);
2498   int count = last.code() - first.code() + 1;
2499   emit(cond | B27 | B26 | am | d*B22 | B20 | base.code()*B16 | sd*B12 |
2500        0xA*B8 | count);
2501 }
2502 
2503 
vstm(BlockAddrMode am,Register base,SwVfpRegister first,SwVfpRegister last,Condition cond)2504 void  Assembler::vstm(BlockAddrMode am,
2505                       Register base,
2506                       SwVfpRegister first,
2507                       SwVfpRegister last,
2508                       Condition cond) {
2509   // Instruction details available in ARM DDI 0406A, A8-784.
2510   // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
2511   // first(15-12) | 1011(11-8) | (count/2)
2512   DCHECK_LE(first.code(), last.code());
2513   DCHECK(am == ia || am == ia_w || am == db_w);
2514   DCHECK(!base.is(pc));
2515 
2516   int sd, d;
2517   first.split_code(&sd, &d);
2518   int count = last.code() - first.code() + 1;
2519   emit(cond | B27 | B26 | am | d*B22 | base.code()*B16 | sd*B12 |
2520        0xA*B8 | count);
2521 }
2522 
2523 
vmov(const SwVfpRegister dst,float imm)2524 void Assembler::vmov(const SwVfpRegister dst, float imm) {
2525   mov(ip, Operand(bit_cast<int32_t>(imm)));
2526   vmov(dst, ip);
2527 }
2528 
2529 
DoubleAsTwoUInt32(double d,uint32_t * lo,uint32_t * hi)2530 static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
2531   uint64_t i;
2532   memcpy(&i, &d, 8);
2533 
2534   *lo = i & 0xffffffff;
2535   *hi = i >> 32;
2536 }
2537 
2538 
2539 // Only works for little endian floating point formats.
2540 // We don't support VFP on the mixed endian floating point platform.
FitsVMOVDoubleImmediate(double d,uint32_t * encoding)2541 static bool FitsVMOVDoubleImmediate(double d, uint32_t *encoding) {
2542   DCHECK(CpuFeatures::IsSupported(VFP3));
2543 
2544   // VMOV can accept an immediate of the form:
2545   //
2546   //  +/- m * 2^(-n) where 16 <= m <= 31 and 0 <= n <= 7
2547   //
2548   // The immediate is encoded using an 8-bit quantity, comprised of two
2549   // 4-bit fields. For an 8-bit immediate of the form:
2550   //
2551   //  [abcdefgh]
2552   //
2553   // where a is the MSB and h is the LSB, an immediate 64-bit double can be
2554   // created of the form:
2555   //
2556   //  [aBbbbbbb,bbcdefgh,00000000,00000000,
2557   //      00000000,00000000,00000000,00000000]
2558   //
2559   // where B = ~b.
2560   //
2561 
2562   uint32_t lo, hi;
2563   DoubleAsTwoUInt32(d, &lo, &hi);
2564 
2565   // The most obvious constraint is the long block of zeroes.
2566   if ((lo != 0) || ((hi & 0xffff) != 0)) {
2567     return false;
2568   }
2569 
2570   // Bits 62:55 must be all clear or all set.
2571   if (((hi & 0x3fc00000) != 0) && ((hi & 0x3fc00000) != 0x3fc00000)) {
2572     return false;
2573   }
2574 
2575   // Bit 63 must be NOT bit 62.
2576   if (((hi ^ (hi << 1)) & (0x40000000)) == 0) {
2577     return false;
2578   }
2579 
2580   // Create the encoded immediate in the form:
2581   //  [00000000,0000abcd,00000000,0000efgh]
2582   *encoding  = (hi >> 16) & 0xf;      // Low nybble.
2583   *encoding |= (hi >> 4) & 0x70000;   // Low three bits of the high nybble.
2584   *encoding |= (hi >> 12) & 0x80000;  // Top bit of the high nybble.
2585 
2586   return true;
2587 }
2588 
2589 
vmov(const DwVfpRegister dst,double imm,const Register scratch)2590 void Assembler::vmov(const DwVfpRegister dst,
2591                      double imm,
2592                      const Register scratch) {
2593   uint32_t enc;
2594   // If the embedded constant pool is disabled, we can use the normal, inline
2595   // constant pool. If the embedded constant pool is enabled (via
2596   // FLAG_enable_embedded_constant_pool), we can only use it where the pool
2597   // pointer (pp) is valid.
2598   bool can_use_pool =
2599       !FLAG_enable_embedded_constant_pool || is_constant_pool_available();
2600   if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) {
2601     // The double can be encoded in the instruction.
2602     //
2603     // Dd = immediate
2604     // Instruction details available in ARM DDI 0406C.b, A8-936.
2605     // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) |
2606     // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0)
2607     int vd, d;
2608     dst.split_code(&vd, &d);
2609     emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc);
2610   } else if (FLAG_enable_vldr_imm && can_use_pool) {
2611     // TODO(jfb) Temporarily turned off until we have constant blinding or
2612     //           some equivalent mitigation: an attacker can otherwise control
2613     //           generated data which also happens to be executable, a Very Bad
2614     //           Thing indeed.
2615     //           Blinding gets tricky because we don't have xor, we probably
2616     //           need to add/subtract without losing precision, which requires a
2617     //           cookie value that Lithium is probably better positioned to
2618     //           choose.
2619     //           We could also add a few peepholes here like detecting 0.0 and
2620     //           -0.0 and doing a vmov from the sequestered d14, forcing denorms
2621     //           to zero (we set flush-to-zero), and normalizing NaN values.
2622     //           We could also detect redundant values.
2623     //           The code could also randomize the order of values, though
2624     //           that's tricky because vldr has a limited reach. Furthermore
2625     //           it breaks load locality.
2626     ConstantPoolEntry::Access access = ConstantPoolAddEntry(pc_offset(), imm);
2627     if (access == ConstantPoolEntry::OVERFLOWED) {
2628       DCHECK(FLAG_enable_embedded_constant_pool);
2629       // Emit instructions to load constant pool offset.
2630       movw(ip, 0);
2631       movt(ip, 0);
2632       // Load from constant pool at offset.
2633       vldr(dst, MemOperand(pp, ip));
2634     } else {
2635       DCHECK(access == ConstantPoolEntry::REGULAR);
2636       vldr(dst, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0));
2637     }
2638   } else {
2639     // Synthesise the double from ARM immediates.
2640     uint32_t lo, hi;
2641     DoubleAsTwoUInt32(imm, &lo, &hi);
2642 
2643     if (lo == hi) {
2644       // Move the low and high parts of the double to a D register in one
2645       // instruction.
2646       mov(ip, Operand(lo));
2647       vmov(dst, ip, ip);
2648     } else if (scratch.is(no_reg)) {
2649       mov(ip, Operand(lo));
2650       vmov(dst, VmovIndexLo, ip);
2651       if (((lo & 0xffff) == (hi & 0xffff)) &&
2652           CpuFeatures::IsSupported(ARMv7)) {
2653         movt(ip, hi >> 16);
2654       } else {
2655         mov(ip, Operand(hi));
2656       }
2657       vmov(dst, VmovIndexHi, ip);
2658     } else {
2659       // Move the low and high parts of the double to a D register in one
2660       // instruction.
2661       mov(ip, Operand(lo));
2662       mov(scratch, Operand(hi));
2663       vmov(dst, ip, scratch);
2664     }
2665   }
2666 }
2667 
2668 
vmov(const SwVfpRegister dst,const SwVfpRegister src,const Condition cond)2669 void Assembler::vmov(const SwVfpRegister dst,
2670                      const SwVfpRegister src,
2671                      const Condition cond) {
2672   // Sd = Sm
2673   // Instruction details available in ARM DDI 0406B, A8-642.
2674   int sd, d, sm, m;
2675   dst.split_code(&sd, &d);
2676   src.split_code(&sm, &m);
2677   emit(cond | 0xE*B24 | d*B22 | 0xB*B20 | sd*B12 | 0xA*B8 | B6 | m*B5 | sm);
2678 }
2679 
2680 
vmov(const DwVfpRegister dst,const DwVfpRegister src,const Condition cond)2681 void Assembler::vmov(const DwVfpRegister dst,
2682                      const DwVfpRegister src,
2683                      const Condition cond) {
2684   // Dd = Dm
2685   // Instruction details available in ARM DDI 0406C.b, A8-938.
2686   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
2687   // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2688   int vd, d;
2689   dst.split_code(&vd, &d);
2690   int vm, m;
2691   src.split_code(&vm, &m);
2692   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B6 | m*B5 |
2693        vm);
2694 }
2695 
2696 
vmov(const DwVfpRegister dst,const VmovIndex index,const Register src,const Condition cond)2697 void Assembler::vmov(const DwVfpRegister dst,
2698                      const VmovIndex index,
2699                      const Register src,
2700                      const Condition cond) {
2701   // Dd[index] = Rt
2702   // Instruction details available in ARM DDI 0406C.b, A8-940.
2703   // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) |
2704   // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
2705   DCHECK(index.index == 0 || index.index == 1);
2706   int vd, d;
2707   dst.split_code(&vd, &d);
2708   emit(cond | 0xE*B24 | index.index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 |
2709        d*B7 | B4);
2710 }
2711 
2712 
vmov(const Register dst,const VmovIndex index,const DwVfpRegister src,const Condition cond)2713 void Assembler::vmov(const Register dst,
2714                      const VmovIndex index,
2715                      const DwVfpRegister src,
2716                      const Condition cond) {
2717   // Dd[index] = Rt
2718   // Instruction details available in ARM DDI 0406C.b, A8.8.342.
2719   // cond(31-28) | 1110(27-24) | U=0(23) | opc1=0index(22-21) | 1(20) |
2720   // Vn(19-16) | Rt(15-12) | 1011(11-8) | N(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
2721   DCHECK(index.index == 0 || index.index == 1);
2722   int vn, n;
2723   src.split_code(&vn, &n);
2724   emit(cond | 0xE*B24 | index.index*B21 | B20 | vn*B16 | dst.code()*B12 |
2725        0xB*B8 | n*B7 | B4);
2726 }
2727 
2728 
vmov(const DwVfpRegister dst,const Register src1,const Register src2,const Condition cond)2729 void Assembler::vmov(const DwVfpRegister dst,
2730                      const Register src1,
2731                      const Register src2,
2732                      const Condition cond) {
2733   // Dm = <Rt,Rt2>.
2734   // Instruction details available in ARM DDI 0406C.b, A8-948.
2735   // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
2736   // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
2737   DCHECK(!src1.is(pc) && !src2.is(pc));
2738   int vm, m;
2739   dst.split_code(&vm, &m);
2740   emit(cond | 0xC*B24 | B22 | src2.code()*B16 |
2741        src1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm);
2742 }
2743 
2744 
vmov(const Register dst1,const Register dst2,const DwVfpRegister src,const Condition cond)2745 void Assembler::vmov(const Register dst1,
2746                      const Register dst2,
2747                      const DwVfpRegister src,
2748                      const Condition cond) {
2749   // <Rt,Rt2> = Dm.
2750   // Instruction details available in ARM DDI 0406C.b, A8-948.
2751   // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
2752   // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
2753   DCHECK(!dst1.is(pc) && !dst2.is(pc));
2754   int vm, m;
2755   src.split_code(&vm, &m);
2756   emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 |
2757        dst1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm);
2758 }
2759 
2760 
vmov(const SwVfpRegister dst,const Register src,const Condition cond)2761 void Assembler::vmov(const SwVfpRegister dst,
2762                      const Register src,
2763                      const Condition cond) {
2764   // Sn = Rt.
2765   // Instruction details available in ARM DDI 0406A, A8-642.
2766   // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
2767   // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
2768   DCHECK(!src.is(pc));
2769   int sn, n;
2770   dst.split_code(&sn, &n);
2771   emit(cond | 0xE*B24 | sn*B16 | src.code()*B12 | 0xA*B8 | n*B7 | B4);
2772 }
2773 
2774 
vmov(const Register dst,const SwVfpRegister src,const Condition cond)2775 void Assembler::vmov(const Register dst,
2776                      const SwVfpRegister src,
2777                      const Condition cond) {
2778   // Rt = Sn.
2779   // Instruction details available in ARM DDI 0406A, A8-642.
2780   // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
2781   // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
2782   DCHECK(!dst.is(pc));
2783   int sn, n;
2784   src.split_code(&sn, &n);
2785   emit(cond | 0xE*B24 | B20 | sn*B16 | dst.code()*B12 | 0xA*B8 | n*B7 | B4);
2786 }
2787 
2788 
2789 // Type of data to read from or write to VFP register.
2790 // Used as specifier in generic vcvt instruction.
2791 enum VFPType { S32, U32, F32, F64 };
2792 
2793 
IsSignedVFPType(VFPType type)2794 static bool IsSignedVFPType(VFPType type) {
2795   switch (type) {
2796     case S32:
2797       return true;
2798     case U32:
2799       return false;
2800     default:
2801       UNREACHABLE();
2802       return false;
2803   }
2804 }
2805 
2806 
IsIntegerVFPType(VFPType type)2807 static bool IsIntegerVFPType(VFPType type) {
2808   switch (type) {
2809     case S32:
2810     case U32:
2811       return true;
2812     case F32:
2813     case F64:
2814       return false;
2815     default:
2816       UNREACHABLE();
2817       return false;
2818   }
2819 }
2820 
2821 
IsDoubleVFPType(VFPType type)2822 static bool IsDoubleVFPType(VFPType type) {
2823   switch (type) {
2824     case F32:
2825       return false;
2826     case F64:
2827       return true;
2828     default:
2829       UNREACHABLE();
2830       return false;
2831   }
2832 }
2833 
2834 
2835 // Split five bit reg_code based on size of reg_type.
2836 //  32-bit register codes are Vm:M
2837 //  64-bit register codes are M:Vm
2838 // where Vm is four bits, and M is a single bit.
SplitRegCode(VFPType reg_type,int reg_code,int * vm,int * m)2839 static void SplitRegCode(VFPType reg_type,
2840                          int reg_code,
2841                          int* vm,
2842                          int* m) {
2843   DCHECK((reg_code >= 0) && (reg_code <= 31));
2844   if (IsIntegerVFPType(reg_type) || !IsDoubleVFPType(reg_type)) {
2845     // 32 bit type.
2846     *m  = reg_code & 0x1;
2847     *vm = reg_code >> 1;
2848   } else {
2849     // 64 bit type.
2850     *m  = (reg_code & 0x10) >> 4;
2851     *vm = reg_code & 0x0F;
2852   }
2853 }
2854 
2855 
2856 // Encode vcvt.src_type.dst_type instruction.
EncodeVCVT(const VFPType dst_type,const int dst_code,const VFPType src_type,const int src_code,VFPConversionMode mode,const Condition cond)2857 static Instr EncodeVCVT(const VFPType dst_type,
2858                         const int dst_code,
2859                         const VFPType src_type,
2860                         const int src_code,
2861                         VFPConversionMode mode,
2862                         const Condition cond) {
2863   DCHECK(src_type != dst_type);
2864   int D, Vd, M, Vm;
2865   SplitRegCode(src_type, src_code, &Vm, &M);
2866   SplitRegCode(dst_type, dst_code, &Vd, &D);
2867 
2868   if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
2869     // Conversion between IEEE floating point and 32-bit integer.
2870     // Instruction details available in ARM DDI 0406B, A8.6.295.
2871     // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
2872     // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2873     DCHECK(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
2874 
2875     int sz, opc2, op;
2876 
2877     if (IsIntegerVFPType(dst_type)) {
2878       opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
2879       sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
2880       op = mode;
2881     } else {
2882       DCHECK(IsIntegerVFPType(src_type));
2883       opc2 = 0x0;
2884       sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
2885       op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
2886     }
2887 
2888     return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 |
2889             Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm);
2890   } else {
2891     // Conversion between IEEE double and single precision.
2892     // Instruction details available in ARM DDI 0406B, A8.6.298.
2893     // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) |
2894     // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2895     int sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
2896     return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 |
2897             Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm);
2898   }
2899 }
2900 
2901 
vcvt_f64_s32(const DwVfpRegister dst,const SwVfpRegister src,VFPConversionMode mode,const Condition cond)2902 void Assembler::vcvt_f64_s32(const DwVfpRegister dst,
2903                              const SwVfpRegister src,
2904                              VFPConversionMode mode,
2905                              const Condition cond) {
2906   emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
2907 }
2908 
2909 
vcvt_f32_s32(const SwVfpRegister dst,const SwVfpRegister src,VFPConversionMode mode,const Condition cond)2910 void Assembler::vcvt_f32_s32(const SwVfpRegister dst,
2911                              const SwVfpRegister src,
2912                              VFPConversionMode mode,
2913                              const Condition cond) {
2914   emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
2915 }
2916 
2917 
vcvt_f64_u32(const DwVfpRegister dst,const SwVfpRegister src,VFPConversionMode mode,const Condition cond)2918 void Assembler::vcvt_f64_u32(const DwVfpRegister dst,
2919                              const SwVfpRegister src,
2920                              VFPConversionMode mode,
2921                              const Condition cond) {
2922   emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
2923 }
2924 
2925 
vcvt_s32_f64(const SwVfpRegister dst,const DwVfpRegister src,VFPConversionMode mode,const Condition cond)2926 void Assembler::vcvt_s32_f64(const SwVfpRegister dst,
2927                              const DwVfpRegister src,
2928                              VFPConversionMode mode,
2929                              const Condition cond) {
2930   emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
2931 }
2932 
2933 
vcvt_u32_f64(const SwVfpRegister dst,const DwVfpRegister src,VFPConversionMode mode,const Condition cond)2934 void Assembler::vcvt_u32_f64(const SwVfpRegister dst,
2935                              const DwVfpRegister src,
2936                              VFPConversionMode mode,
2937                              const Condition cond) {
2938   emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
2939 }
2940 
2941 
vcvt_f64_f32(const DwVfpRegister dst,const SwVfpRegister src,VFPConversionMode mode,const Condition cond)2942 void Assembler::vcvt_f64_f32(const DwVfpRegister dst,
2943                              const SwVfpRegister src,
2944                              VFPConversionMode mode,
2945                              const Condition cond) {
2946   emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
2947 }
2948 
2949 
vcvt_f32_f64(const SwVfpRegister dst,const DwVfpRegister src,VFPConversionMode mode,const Condition cond)2950 void Assembler::vcvt_f32_f64(const SwVfpRegister dst,
2951                              const DwVfpRegister src,
2952                              VFPConversionMode mode,
2953                              const Condition cond) {
2954   emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
2955 }
2956 
2957 
vcvt_f64_s32(const DwVfpRegister dst,int fraction_bits,const Condition cond)2958 void Assembler::vcvt_f64_s32(const DwVfpRegister dst,
2959                              int fraction_bits,
2960                              const Condition cond) {
2961   // Instruction details available in ARM DDI 0406C.b, A8-874.
2962   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 1010(19-16) | Vd(15-12) |
2963   // 101(11-9) | sf=1(8) | sx=1(7) | 1(6) | i(5) | 0(4) | imm4(3-0)
2964   DCHECK(fraction_bits > 0 && fraction_bits <= 32);
2965   DCHECK(CpuFeatures::IsSupported(VFP3));
2966   int vd, d;
2967   dst.split_code(&vd, &d);
2968   int imm5 = 32 - fraction_bits;
2969   int i = imm5 & 1;
2970   int imm4 = (imm5 >> 1) & 0xf;
2971   emit(cond | 0xE*B24 | B23 | d*B22 | 0x3*B20 | B19 | 0x2*B16 |
2972        vd*B12 | 0x5*B9 | B8 | B7 | B6 | i*B5 | imm4);
2973 }
2974 
2975 
vneg(const DwVfpRegister dst,const DwVfpRegister src,const Condition cond)2976 void Assembler::vneg(const DwVfpRegister dst,
2977                      const DwVfpRegister src,
2978                      const Condition cond) {
2979   // Instruction details available in ARM DDI 0406C.b, A8-968.
2980   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
2981   // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2982   int vd, d;
2983   dst.split_code(&vd, &d);
2984   int vm, m;
2985   src.split_code(&vm, &m);
2986 
2987   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 |
2988        m*B5 | vm);
2989 }
2990 
2991 
vneg(const SwVfpRegister dst,const SwVfpRegister src,const Condition cond)2992 void Assembler::vneg(const SwVfpRegister dst, const SwVfpRegister src,
2993                      const Condition cond) {
2994   // Instruction details available in ARM DDI 0406C.b, A8-968.
2995   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
2996   // 101(11-9) | sz=0(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
2997   int vd, d;
2998   dst.split_code(&vd, &d);
2999   int vm, m;
3000   src.split_code(&vm, &m);
3001 
3002   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
3003        B6 | m * B5 | vm);
3004 }
3005 
3006 
vabs(const DwVfpRegister dst,const DwVfpRegister src,const Condition cond)3007 void Assembler::vabs(const DwVfpRegister dst,
3008                      const DwVfpRegister src,
3009                      const Condition cond) {
3010   // Instruction details available in ARM DDI 0406C.b, A8-524.
3011   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
3012   // 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3013   int vd, d;
3014   dst.split_code(&vd, &d);
3015   int vm, m;
3016   src.split_code(&vm, &m);
3017   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B7 | B6 |
3018        m*B5 | vm);
3019 }
3020 
3021 
vabs(const SwVfpRegister dst,const SwVfpRegister src,const Condition cond)3022 void Assembler::vabs(const SwVfpRegister dst, const SwVfpRegister src,
3023                      const Condition cond) {
3024   // Instruction details available in ARM DDI 0406C.b, A8-524.
3025   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
3026   // 101(11-9) | sz=0(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3027   int vd, d;
3028   dst.split_code(&vd, &d);
3029   int vm, m;
3030   src.split_code(&vm, &m);
3031   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | vd * B12 | 0x5 * B9 | B7 | B6 |
3032        m * B5 | vm);
3033 }
3034 
3035 
vadd(const DwVfpRegister dst,const DwVfpRegister src1,const DwVfpRegister src2,const Condition cond)3036 void Assembler::vadd(const DwVfpRegister dst,
3037                      const DwVfpRegister src1,
3038                      const DwVfpRegister src2,
3039                      const Condition cond) {
3040   // Dd = vadd(Dn, Dm) double precision floating point addition.
3041   // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3042   // Instruction details available in ARM DDI 0406C.b, A8-830.
3043   // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3044   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3045   int vd, d;
3046   dst.split_code(&vd, &d);
3047   int vn, n;
3048   src1.split_code(&vn, &n);
3049   int vm, m;
3050   src2.split_code(&vm, &m);
3051   emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
3052        n*B7 | m*B5 | vm);
3053 }
3054 
3055 
vadd(const SwVfpRegister dst,const SwVfpRegister src1,const SwVfpRegister src2,const Condition cond)3056 void Assembler::vadd(const SwVfpRegister dst, const SwVfpRegister src1,
3057                      const SwVfpRegister src2, const Condition cond) {
3058   // Sd = vadd(Sn, Sm) single precision floating point addition.
3059   // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3060   // Instruction details available in ARM DDI 0406C.b, A8-830.
3061   // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3062   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3063   int vd, d;
3064   dst.split_code(&vd, &d);
3065   int vn, n;
3066   src1.split_code(&vn, &n);
3067   int vm, m;
3068   src2.split_code(&vm, &m);
3069   emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
3070        0x5 * B9 | n * B7 | m * B5 | vm);
3071 }
3072 
3073 
vsub(const DwVfpRegister dst,const DwVfpRegister src1,const DwVfpRegister src2,const Condition cond)3074 void Assembler::vsub(const DwVfpRegister dst,
3075                      const DwVfpRegister src1,
3076                      const DwVfpRegister src2,
3077                      const Condition cond) {
3078   // Dd = vsub(Dn, Dm) double precision floating point subtraction.
3079   // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3080   // Instruction details available in ARM DDI 0406C.b, A8-1086.
3081   // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3082   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3083   int vd, d;
3084   dst.split_code(&vd, &d);
3085   int vn, n;
3086   src1.split_code(&vn, &n);
3087   int vm, m;
3088   src2.split_code(&vm, &m);
3089   emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
3090        n*B7 | B6 | m*B5 | vm);
3091 }
3092 
3093 
vsub(const SwVfpRegister dst,const SwVfpRegister src1,const SwVfpRegister src2,const Condition cond)3094 void Assembler::vsub(const SwVfpRegister dst, const SwVfpRegister src1,
3095                      const SwVfpRegister src2, const Condition cond) {
3096   // Sd = vsub(Sn, Sm) single precision floating point subtraction.
3097   // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3098   // Instruction details available in ARM DDI 0406C.b, A8-1086.
3099   // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
3100   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3101   int vd, d;
3102   dst.split_code(&vd, &d);
3103   int vn, n;
3104   src1.split_code(&vn, &n);
3105   int vm, m;
3106   src2.split_code(&vm, &m);
3107   emit(cond | 0x1C * B23 | d * B22 | 0x3 * B20 | vn * B16 | vd * B12 |
3108        0x5 * B9 | n * B7 | B6 | m * B5 | vm);
3109 }
3110 
3111 
vmul(const DwVfpRegister dst,const DwVfpRegister src1,const DwVfpRegister src2,const Condition cond)3112 void Assembler::vmul(const DwVfpRegister dst,
3113                      const DwVfpRegister src1,
3114                      const DwVfpRegister src2,
3115                      const Condition cond) {
3116   // Dd = vmul(Dn, Dm) double precision floating point multiplication.
3117   // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3118   // Instruction details available in ARM DDI 0406C.b, A8-960.
3119   // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
3120   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3121   int vd, d;
3122   dst.split_code(&vd, &d);
3123   int vn, n;
3124   src1.split_code(&vn, &n);
3125   int vm, m;
3126   src2.split_code(&vm, &m);
3127   emit(cond | 0x1C*B23 | d*B22 | 0x2*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 |
3128        n*B7 | m*B5 | vm);
3129 }
3130 
3131 
vmul(const SwVfpRegister dst,const SwVfpRegister src1,const SwVfpRegister src2,const Condition cond)3132 void Assembler::vmul(const SwVfpRegister dst, const SwVfpRegister src1,
3133                      const SwVfpRegister src2, const Condition cond) {
3134   // Sd = vmul(Sn, Sm) single precision floating point multiplication.
3135   // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3136   // Instruction details available in ARM DDI 0406C.b, A8-960.
3137   // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
3138   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3139   int vd, d;
3140   dst.split_code(&vd, &d);
3141   int vn, n;
3142   src1.split_code(&vn, &n);
3143   int vm, m;
3144   src2.split_code(&vm, &m);
3145   emit(cond | 0x1C * B23 | d * B22 | 0x2 * B20 | vn * B16 | vd * B12 |
3146        0x5 * B9 | n * B7 | m * B5 | vm);
3147 }
3148 
3149 
vmla(const DwVfpRegister dst,const DwVfpRegister src1,const DwVfpRegister src2,const Condition cond)3150 void Assembler::vmla(const DwVfpRegister dst,
3151                      const DwVfpRegister src1,
3152                      const DwVfpRegister src2,
3153                      const Condition cond) {
3154   // Instruction details available in ARM DDI 0406C.b, A8-932.
3155   // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3156   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0)
3157   int vd, d;
3158   dst.split_code(&vd, &d);
3159   int vn, n;
3160   src1.split_code(&vn, &n);
3161   int vm, m;
3162   src2.split_code(&vm, &m);
3163   emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 |
3164        vm);
3165 }
3166 
3167 
vmla(const SwVfpRegister dst,const SwVfpRegister src1,const SwVfpRegister src2,const Condition cond)3168 void Assembler::vmla(const SwVfpRegister dst, const SwVfpRegister src1,
3169                      const SwVfpRegister src2, const Condition cond) {
3170   // Instruction details available in ARM DDI 0406C.b, A8-932.
3171   // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3172   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0)
3173   int vd, d;
3174   dst.split_code(&vd, &d);
3175   int vn, n;
3176   src1.split_code(&vn, &n);
3177   int vm, m;
3178   src2.split_code(&vm, &m);
3179   emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
3180        m * B5 | vm);
3181 }
3182 
3183 
vmls(const DwVfpRegister dst,const DwVfpRegister src1,const DwVfpRegister src2,const Condition cond)3184 void Assembler::vmls(const DwVfpRegister dst,
3185                      const DwVfpRegister src1,
3186                      const DwVfpRegister src2,
3187                      const Condition cond) {
3188   // Instruction details available in ARM DDI 0406C.b, A8-932.
3189   // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3190   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0)
3191   int vd, d;
3192   dst.split_code(&vd, &d);
3193   int vn, n;
3194   src1.split_code(&vn, &n);
3195   int vm, m;
3196   src2.split_code(&vm, &m);
3197   emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | B6 |
3198        m*B5 | vm);
3199 }
3200 
3201 
vmls(const SwVfpRegister dst,const SwVfpRegister src1,const SwVfpRegister src2,const Condition cond)3202 void Assembler::vmls(const SwVfpRegister dst, const SwVfpRegister src1,
3203                      const SwVfpRegister src2, const Condition cond) {
3204   // Instruction details available in ARM DDI 0406C.b, A8-932.
3205   // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) |
3206   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | op=1(6) | M(5) | 0(4) | Vm(3-0)
3207   int vd, d;
3208   dst.split_code(&vd, &d);
3209   int vn, n;
3210   src1.split_code(&vn, &n);
3211   int vm, m;
3212   src2.split_code(&vm, &m);
3213   emit(cond | 0x1C * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
3214        B6 | m * B5 | vm);
3215 }
3216 
3217 
vdiv(const DwVfpRegister dst,const DwVfpRegister src1,const DwVfpRegister src2,const Condition cond)3218 void Assembler::vdiv(const DwVfpRegister dst,
3219                      const DwVfpRegister src1,
3220                      const DwVfpRegister src2,
3221                      const Condition cond) {
3222   // Dd = vdiv(Dn, Dm) double precision floating point division.
3223   // Dd = D:Vd; Dm=M:Vm; Dn=N:Vm.
3224   // Instruction details available in ARM DDI 0406C.b, A8-882.
3225   // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
3226   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3227   int vd, d;
3228   dst.split_code(&vd, &d);
3229   int vn, n;
3230   src1.split_code(&vn, &n);
3231   int vm, m;
3232   src2.split_code(&vm, &m);
3233   emit(cond | 0x1D*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 |
3234        vm);
3235 }
3236 
3237 
vdiv(const SwVfpRegister dst,const SwVfpRegister src1,const SwVfpRegister src2,const Condition cond)3238 void Assembler::vdiv(const SwVfpRegister dst, const SwVfpRegister src1,
3239                      const SwVfpRegister src2, const Condition cond) {
3240   // Sd = vdiv(Sn, Sm) single precision floating point division.
3241   // Sd = D:Vd; Sm=M:Vm; Sn=N:Vm.
3242   // Instruction details available in ARM DDI 0406C.b, A8-882.
3243   // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
3244   // Vd(15-12) | 101(11-9) | sz=0(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
3245   int vd, d;
3246   dst.split_code(&vd, &d);
3247   int vn, n;
3248   src1.split_code(&vn, &n);
3249   int vm, m;
3250   src2.split_code(&vm, &m);
3251   emit(cond | 0x1D * B23 | d * B22 | vn * B16 | vd * B12 | 0x5 * B9 | n * B7 |
3252        m * B5 | vm);
3253 }
3254 
3255 
vcmp(const DwVfpRegister src1,const DwVfpRegister src2,const Condition cond)3256 void Assembler::vcmp(const DwVfpRegister src1,
3257                      const DwVfpRegister src2,
3258                      const Condition cond) {
3259   // vcmp(Dd, Dm) double precision floating point comparison.
3260   // Instruction details available in ARM DDI 0406C.b, A8-864.
3261   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
3262   // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3263   int vd, d;
3264   src1.split_code(&vd, &d);
3265   int vm, m;
3266   src2.split_code(&vm, &m);
3267   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x4*B16 | vd*B12 | 0x5*B9 | B8 | B6 |
3268        m*B5 | vm);
3269 }
3270 
3271 
vcmp(const SwVfpRegister src1,const SwVfpRegister src2,const Condition cond)3272 void Assembler::vcmp(const SwVfpRegister src1, const SwVfpRegister src2,
3273                      const Condition cond) {
3274   // vcmp(Sd, Sm) single precision floating point comparison.
3275   // Instruction details available in ARM DDI 0406C.b, A8-864.
3276   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
3277   // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3278   int vd, d;
3279   src1.split_code(&vd, &d);
3280   int vm, m;
3281   src2.split_code(&vm, &m);
3282   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x4 * B16 | vd * B12 |
3283        0x5 * B9 | B6 | m * B5 | vm);
3284 }
3285 
3286 
vcmp(const DwVfpRegister src1,const double src2,const Condition cond)3287 void Assembler::vcmp(const DwVfpRegister src1,
3288                      const double src2,
3289                      const Condition cond) {
3290   // vcmp(Dd, #0.0) double precision floating point comparison.
3291   // Instruction details available in ARM DDI 0406C.b, A8-864.
3292   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
3293   // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
3294   DCHECK(src2 == 0.0);
3295   int vd, d;
3296   src1.split_code(&vd, &d);
3297   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x5*B16 | vd*B12 | 0x5*B9 | B8 | B6);
3298 }
3299 
3300 
vcmp(const SwVfpRegister src1,const float src2,const Condition cond)3301 void Assembler::vcmp(const SwVfpRegister src1, const float src2,
3302                      const Condition cond) {
3303   // vcmp(Sd, #0.0) single precision floating point comparison.
3304   // Instruction details available in ARM DDI 0406C.b, A8-864.
3305   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
3306   // Vd(15-12) | 101(11-9) | sz=0(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
3307   DCHECK(src2 == 0.0);
3308   int vd, d;
3309   src1.split_code(&vd, &d);
3310   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x5 * B16 | vd * B12 |
3311        0x5 * B9 | B6);
3312 }
3313 
3314 
vsqrt(const DwVfpRegister dst,const DwVfpRegister src,const Condition cond)3315 void Assembler::vsqrt(const DwVfpRegister dst,
3316                       const DwVfpRegister src,
3317                       const Condition cond) {
3318   // Instruction details available in ARM DDI 0406C.b, A8-1058.
3319   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
3320   // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
3321   int vd, d;
3322   dst.split_code(&vd, &d);
3323   int vm, m;
3324   src.split_code(&vm, &m);
3325   emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | 0x3*B6 |
3326        m*B5 | vm);
3327 }
3328 
3329 
vsqrt(const SwVfpRegister dst,const SwVfpRegister src,const Condition cond)3330 void Assembler::vsqrt(const SwVfpRegister dst, const SwVfpRegister src,
3331                       const Condition cond) {
3332   // Instruction details available in ARM DDI 0406C.b, A8-1058.
3333   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
3334   // Vd(15-12) | 101(11-9) | sz=0(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
3335   int vd, d;
3336   dst.split_code(&vd, &d);
3337   int vm, m;
3338   src.split_code(&vm, &m);
3339   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | B16 | vd * B12 | 0x5 * B9 |
3340        0x3 * B6 | m * B5 | vm);
3341 }
3342 
3343 
vmsr(Register dst,Condition cond)3344 void Assembler::vmsr(Register dst, Condition cond) {
3345   // Instruction details available in ARM DDI 0406A, A8-652.
3346   // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
3347   // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
3348   emit(cond | 0xE * B24 | 0xE * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4);
3349 }
3350 
3351 
vmrs(Register dst,Condition cond)3352 void Assembler::vmrs(Register dst, Condition cond) {
3353   // Instruction details available in ARM DDI 0406A, A8-652.
3354   // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
3355   // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
3356   emit(cond | 0xE * B24 | 0xF * B20 | B16 | dst.code() * B12 | 0xA * B8 | B4);
3357 }
3358 
3359 
vrinta(const SwVfpRegister dst,const SwVfpRegister src)3360 void Assembler::vrinta(const SwVfpRegister dst, const SwVfpRegister src) {
3361   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3362   // 10(19-18) | RM=00(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3363   // M(5) | 0(4) | Vm(3-0)
3364   DCHECK(CpuFeatures::IsSupported(ARMv8));
3365   int vd, d;
3366   dst.split_code(&vd, &d);
3367   int vm, m;
3368   src.split_code(&vm, &m);
3369   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 |
3370        0x5 * B9 | B6 | m * B5 | vm);
3371 }
3372 
3373 
vrinta(const DwVfpRegister dst,const DwVfpRegister src)3374 void Assembler::vrinta(const DwVfpRegister dst, const DwVfpRegister src) {
3375   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3376   // 10(19-18) | RM=00(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3377   // M(5) | 0(4) | Vm(3-0)
3378   DCHECK(CpuFeatures::IsSupported(ARMv8));
3379   int vd, d;
3380   dst.split_code(&vd, &d);
3381   int vm, m;
3382   src.split_code(&vm, &m);
3383   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | vd * B12 |
3384        0x5 * B9 | B8 | B6 | m * B5 | vm);
3385 }
3386 
3387 
vrintn(const SwVfpRegister dst,const SwVfpRegister src)3388 void Assembler::vrintn(const SwVfpRegister dst, const SwVfpRegister src) {
3389   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3390   // 10(19-18) | RM=01(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3391   // M(5) | 0(4) | Vm(3-0)
3392   DCHECK(CpuFeatures::IsSupported(ARMv8));
3393   int vd, d;
3394   dst.split_code(&vd, &d);
3395   int vm, m;
3396   src.split_code(&vm, &m);
3397   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 |
3398        vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
3399 }
3400 
3401 
vrintn(const DwVfpRegister dst,const DwVfpRegister src)3402 void Assembler::vrintn(const DwVfpRegister dst, const DwVfpRegister src) {
3403   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3404   // 10(19-18) | RM=01(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3405   // M(5) | 0(4) | Vm(3-0)
3406   DCHECK(CpuFeatures::IsSupported(ARMv8));
3407   int vd, d;
3408   dst.split_code(&vd, &d);
3409   int vm, m;
3410   src.split_code(&vm, &m);
3411   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x1 * B16 |
3412        vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
3413 }
3414 
3415 
vrintp(const SwVfpRegister dst,const SwVfpRegister src)3416 void Assembler::vrintp(const SwVfpRegister dst, const SwVfpRegister src) {
3417   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3418   // 10(19-18) | RM=10(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3419   // M(5) | 0(4) | Vm(3-0)
3420   DCHECK(CpuFeatures::IsSupported(ARMv8));
3421   int vd, d;
3422   dst.split_code(&vd, &d);
3423   int vm, m;
3424   src.split_code(&vm, &m);
3425   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 |
3426        vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
3427 }
3428 
3429 
vrintp(const DwVfpRegister dst,const DwVfpRegister src)3430 void Assembler::vrintp(const DwVfpRegister dst, const DwVfpRegister src) {
3431   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3432   // 10(19-18) | RM=10(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3433   // M(5) | 0(4) | Vm(3-0)
3434   DCHECK(CpuFeatures::IsSupported(ARMv8));
3435   int vd, d;
3436   dst.split_code(&vd, &d);
3437   int vm, m;
3438   src.split_code(&vm, &m);
3439   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x2 * B16 |
3440        vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
3441 }
3442 
3443 
vrintm(const SwVfpRegister dst,const SwVfpRegister src)3444 void Assembler::vrintm(const SwVfpRegister dst, const SwVfpRegister src) {
3445   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3446   // 10(19-18) | RM=11(17-16) |  Vd(15-12) | 101(11-9) | sz=0(8) | 01(7-6) |
3447   // M(5) | 0(4) | Vm(3-0)
3448   DCHECK(CpuFeatures::IsSupported(ARMv8));
3449   int vd, d;
3450   dst.split_code(&vd, &d);
3451   int vm, m;
3452   src.split_code(&vm, &m);
3453   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 |
3454        vd * B12 | 0x5 * B9 | B6 | m * B5 | vm);
3455 }
3456 
3457 
vrintm(const DwVfpRegister dst,const DwVfpRegister src)3458 void Assembler::vrintm(const DwVfpRegister dst, const DwVfpRegister src) {
3459   // cond=kSpecialCondition(31-28) | 11101(27-23)| D(22) | 11(21-20) |
3460   // 10(19-18) | RM=11(17-16) |  Vd(15-12) | 101(11-9) | sz=1(8) | 01(7-6) |
3461   // M(5) | 0(4) | Vm(3-0)
3462   DCHECK(CpuFeatures::IsSupported(ARMv8));
3463   int vd, d;
3464   dst.split_code(&vd, &d);
3465   int vm, m;
3466   src.split_code(&vm, &m);
3467   emit(kSpecialCondition | 0x1D * B23 | d * B22 | 0x3 * B20 | B19 | 0x3 * B16 |
3468        vd * B12 | 0x5 * B9 | B8 | B6 | m * B5 | vm);
3469 }
3470 
3471 
vrintz(const SwVfpRegister dst,const SwVfpRegister src,const Condition cond)3472 void Assembler::vrintz(const SwVfpRegister dst, const SwVfpRegister src,
3473                        const Condition cond) {
3474   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) |
3475   // Vd(15-12) | 101(11-9) | sz=0(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3476   DCHECK(CpuFeatures::IsSupported(ARMv8));
3477   int vd, d;
3478   dst.split_code(&vd, &d);
3479   int vm, m;
3480   src.split_code(&vm, &m);
3481   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 |
3482        0x5 * B9 | B7 | B6 | m * B5 | vm);
3483 }
3484 
3485 
vrintz(const DwVfpRegister dst,const DwVfpRegister src,const Condition cond)3486 void Assembler::vrintz(const DwVfpRegister dst, const DwVfpRegister src,
3487                        const Condition cond) {
3488   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 011(19-17) | 0(16) |
3489   // Vd(15-12) | 101(11-9) | sz=1(8) | op=1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
3490   DCHECK(CpuFeatures::IsSupported(ARMv8));
3491   int vd, d;
3492   dst.split_code(&vd, &d);
3493   int vm, m;
3494   src.split_code(&vm, &m);
3495   emit(cond | 0x1D * B23 | d * B22 | 0x3 * B20 | 0x3 * B17 | vd * B12 |
3496        0x5 * B9 | B8 | B7 | B6 | m * B5 | vm);
3497 }
3498 
3499 
3500 // Support for NEON.
3501 
vld1(NeonSize size,const NeonListOperand & dst,const NeonMemOperand & src)3502 void Assembler::vld1(NeonSize size,
3503                      const NeonListOperand& dst,
3504                      const NeonMemOperand& src) {
3505   // Instruction details available in ARM DDI 0406C.b, A8.8.320.
3506   // 1111(31-28) | 01000(27-23) | D(22) | 10(21-20) | Rn(19-16) |
3507   // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
3508   DCHECK(CpuFeatures::IsSupported(NEON));
3509   int vd, d;
3510   dst.base().split_code(&vd, &d);
3511   emit(0xFU*B28 | 4*B24 | d*B22 | 2*B20 | src.rn().code()*B16 | vd*B12 |
3512        dst.type()*B8 | size*B6 | src.align()*B4 | src.rm().code());
3513 }
3514 
3515 
vst1(NeonSize size,const NeonListOperand & src,const NeonMemOperand & dst)3516 void Assembler::vst1(NeonSize size,
3517                      const NeonListOperand& src,
3518                      const NeonMemOperand& dst) {
3519   // Instruction details available in ARM DDI 0406C.b, A8.8.404.
3520   // 1111(31-28) | 01000(27-23) | D(22) | 00(21-20) | Rn(19-16) |
3521   // Vd(15-12) | type(11-8) | size(7-6) | align(5-4) | Rm(3-0)
3522   DCHECK(CpuFeatures::IsSupported(NEON));
3523   int vd, d;
3524   src.base().split_code(&vd, &d);
3525   emit(0xFU*B28 | 4*B24 | d*B22 | dst.rn().code()*B16 | vd*B12 | src.type()*B8 |
3526        size*B6 | dst.align()*B4 | dst.rm().code());
3527 }
3528 
3529 
vmovl(NeonDataType dt,QwNeonRegister dst,DwVfpRegister src)3530 void Assembler::vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src) {
3531   // Instruction details available in ARM DDI 0406C.b, A8.8.346.
3532   // 1111(31-28) | 001(27-25) | U(24) | 1(23) | D(22) | imm3(21-19) |
3533   // 000(18-16) | Vd(15-12) | 101000(11-6) | M(5) | 1(4) | Vm(3-0)
3534   DCHECK(CpuFeatures::IsSupported(NEON));
3535   int vd, d;
3536   dst.split_code(&vd, &d);
3537   int vm, m;
3538   src.split_code(&vm, &m);
3539   emit(0xFU*B28 | B25 | (dt & NeonDataTypeUMask) | B23 | d*B22 |
3540         (dt & NeonDataTypeSizeMask)*B19 | vd*B12 | 0xA*B8 | m*B5 | B4 | vm);
3541 }
3542 
3543 
3544 // Pseudo instructions.
nop(int type)3545 void Assembler::nop(int type) {
3546   // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes
3547   // some of the CPU's pipeline and has to issue. Older ARM chips simply used
3548   // MOV Rx, Rx as NOP and it performs better even in newer CPUs.
3549   // We therefore use MOV Rx, Rx, even on newer CPUs, and use Rx to encode
3550   // a type.
3551   DCHECK(0 <= type && type <= 14);  // mov pc, pc isn't a nop.
3552   emit(al | 13*B21 | type*B12 | type);
3553 }
3554 
3555 
IsMovT(Instr instr)3556 bool Assembler::IsMovT(Instr instr) {
3557   instr &= ~(((kNumberOfConditions - 1) << 28) |  // Mask off conditions
3558              ((kNumRegisters-1)*B12) |            // mask out register
3559              EncodeMovwImmediate(0xFFFF));        // mask out immediate value
3560   return instr == kMovtPattern;
3561 }
3562 
3563 
IsMovW(Instr instr)3564 bool Assembler::IsMovW(Instr instr) {
3565   instr &= ~(((kNumberOfConditions - 1) << 28) |  // Mask off conditions
3566              ((kNumRegisters-1)*B12) |            // mask out destination
3567              EncodeMovwImmediate(0xFFFF));        // mask out immediate value
3568   return instr == kMovwPattern;
3569 }
3570 
3571 
GetMovTPattern()3572 Instr Assembler::GetMovTPattern() { return kMovtPattern; }
3573 
3574 
GetMovWPattern()3575 Instr Assembler::GetMovWPattern() { return kMovwPattern; }
3576 
3577 
EncodeMovwImmediate(uint32_t immediate)3578 Instr Assembler::EncodeMovwImmediate(uint32_t immediate) {
3579   DCHECK(immediate < 0x10000);
3580   return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
3581 }
3582 
3583 
PatchMovwImmediate(Instr instruction,uint32_t immediate)3584 Instr Assembler::PatchMovwImmediate(Instr instruction, uint32_t immediate) {
3585   instruction &= ~EncodeMovwImmediate(0xffff);
3586   return instruction | EncodeMovwImmediate(immediate);
3587 }
3588 
3589 
DecodeShiftImm(Instr instr)3590 int Assembler::DecodeShiftImm(Instr instr) {
3591   int rotate = Instruction::RotateValue(instr) * 2;
3592   int immed8 = Instruction::Immed8Value(instr);
3593   return base::bits::RotateRight32(immed8, rotate);
3594 }
3595 
3596 
PatchShiftImm(Instr instr,int immed)3597 Instr Assembler::PatchShiftImm(Instr instr, int immed) {
3598   uint32_t rotate_imm = 0;
3599   uint32_t immed_8 = 0;
3600   bool immed_fits = fits_shifter(immed, &rotate_imm, &immed_8, NULL);
3601   DCHECK(immed_fits);
3602   USE(immed_fits);
3603   return (instr & ~kOff12Mask) | (rotate_imm << 8) | immed_8;
3604 }
3605 
3606 
IsNop(Instr instr,int type)3607 bool Assembler::IsNop(Instr instr, int type) {
3608   DCHECK(0 <= type && type <= 14);  // mov pc, pc isn't a nop.
3609   // Check for mov rx, rx where x = type.
3610   return instr == (al | 13*B21 | type*B12 | type);
3611 }
3612 
3613 
IsMovImmed(Instr instr)3614 bool Assembler::IsMovImmed(Instr instr) {
3615   return (instr & kMovImmedMask) == kMovImmedPattern;
3616 }
3617 
3618 
IsOrrImmed(Instr instr)3619 bool Assembler::IsOrrImmed(Instr instr) {
3620   return (instr & kOrrImmedMask) == kOrrImmedPattern;
3621 }
3622 
3623 
3624 // static
ImmediateFitsAddrMode1Instruction(int32_t imm32)3625 bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
3626   uint32_t dummy1;
3627   uint32_t dummy2;
3628   return fits_shifter(imm32, &dummy1, &dummy2, NULL);
3629 }
3630 
3631 
ImmediateFitsAddrMode2Instruction(int32_t imm32)3632 bool Assembler::ImmediateFitsAddrMode2Instruction(int32_t imm32) {
3633   return is_uint12(abs(imm32));
3634 }
3635 
3636 
3637 // Debugging.
RecordConstPool(int size)3638 void Assembler::RecordConstPool(int size) {
3639   // We only need this for debugger support, to correctly compute offsets in the
3640   // code.
3641   RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size));
3642 }
3643 
3644 
GrowBuffer()3645 void Assembler::GrowBuffer() {
3646   if (!own_buffer_) FATAL("external code buffer is too small");
3647 
3648   // Compute new buffer size.
3649   CodeDesc desc;  // the new buffer
3650   if (buffer_size_ < 1 * MB) {
3651     desc.buffer_size = 2*buffer_size_;
3652   } else {
3653     desc.buffer_size = buffer_size_ + 1*MB;
3654   }
3655   CHECK_GT(desc.buffer_size, 0);  // no overflow
3656 
3657   // Set up new buffer.
3658   desc.buffer = NewArray<byte>(desc.buffer_size);
3659 
3660   desc.instr_size = pc_offset();
3661   desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
3662   desc.origin = this;
3663 
3664   // Copy the data.
3665   int pc_delta = desc.buffer - buffer_;
3666   int rc_delta = (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_);
3667   MemMove(desc.buffer, buffer_, desc.instr_size);
3668   MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(),
3669           desc.reloc_size);
3670 
3671   // Switch buffers.
3672   DeleteArray(buffer_);
3673   buffer_ = desc.buffer;
3674   buffer_size_ = desc.buffer_size;
3675   pc_ += pc_delta;
3676   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
3677                                reloc_info_writer.last_pc() + pc_delta);
3678 
3679   // None of our relocation types are pc relative pointing outside the code
3680   // buffer nor pc absolute pointing inside the code buffer, so there is no need
3681   // to relocate any emitted relocation entries.
3682 }
3683 
3684 
db(uint8_t data)3685 void Assembler::db(uint8_t data) {
3686   // db is used to write raw data. The constant pool should be emitted or
3687   // blocked before using db.
3688   DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0));
3689   DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0));
3690   CheckBuffer();
3691   *reinterpret_cast<uint8_t*>(pc_) = data;
3692   pc_ += sizeof(uint8_t);
3693 }
3694 
3695 
dd(uint32_t data)3696 void Assembler::dd(uint32_t data) {
3697   // dd is used to write raw data. The constant pool should be emitted or
3698   // blocked before using dd.
3699   DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0));
3700   DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0));
3701   CheckBuffer();
3702   *reinterpret_cast<uint32_t*>(pc_) = data;
3703   pc_ += sizeof(uint32_t);
3704 }
3705 
3706 
dq(uint64_t value)3707 void Assembler::dq(uint64_t value) {
3708   // dq is used to write raw data. The constant pool should be emitted or
3709   // blocked before using dq.
3710   DCHECK(is_const_pool_blocked() || (num_pending_32_bit_constants_ == 0));
3711   DCHECK(is_const_pool_blocked() || (num_pending_64_bit_constants_ == 0));
3712   CheckBuffer();
3713   *reinterpret_cast<uint64_t*>(pc_) = value;
3714   pc_ += sizeof(uint64_t);
3715 }
3716 
3717 
emit_code_stub_address(Code * stub)3718 void Assembler::emit_code_stub_address(Code* stub) {
3719   CheckBuffer();
3720   *reinterpret_cast<uint32_t*>(pc_) =
3721       reinterpret_cast<uint32_t>(stub->instruction_start());
3722   pc_ += sizeof(uint32_t);
3723 }
3724 
3725 
RecordRelocInfo(RelocInfo::Mode rmode,intptr_t data)3726 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
3727   if (RelocInfo::IsNone(rmode) ||
3728       // Don't record external references unless the heap will be serialized.
3729       (rmode == RelocInfo::EXTERNAL_REFERENCE && !serializer_enabled() &&
3730        !emit_debug_code())) {
3731     return;
3732   }
3733   DCHECK(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
3734   if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
3735     data = RecordedAstId().ToInt();
3736     ClearRecordedAstId();
3737   }
3738   RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
3739   reloc_info_writer.Write(&rinfo);
3740 }
3741 
3742 
ConstantPoolAddEntry(int position,RelocInfo::Mode rmode,intptr_t value)3743 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
3744                                                           RelocInfo::Mode rmode,
3745                                                           intptr_t value) {
3746   DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::POSITION &&
3747          rmode != RelocInfo::STATEMENT_POSITION &&
3748          rmode != RelocInfo::CONST_POOL && rmode != RelocInfo::NONE64);
3749   bool sharing_ok = RelocInfo::IsNone(rmode) ||
3750                     !(serializer_enabled() || rmode < RelocInfo::CELL);
3751   if (FLAG_enable_embedded_constant_pool) {
3752     return constant_pool_builder_.AddEntry(position, value, sharing_ok);
3753   } else {
3754     DCHECK(num_pending_32_bit_constants_ < kMaxNumPending32Constants);
3755     if (num_pending_32_bit_constants_ == 0) {
3756       first_const_pool_32_use_ = position;
3757     } else if (num_pending_32_bit_constants_ == kMinNumPendingConstants &&
3758                pending_32_bit_constants_ ==
3759                    &pending_32_bit_constants_buffer_[0]) {
3760       // Inline buffer is full, switch to dynamically allocated buffer.
3761       pending_32_bit_constants_ =
3762           new ConstantPoolEntry[kMaxNumPending32Constants];
3763       std::copy(&pending_32_bit_constants_buffer_[0],
3764                 &pending_32_bit_constants_buffer_[kMinNumPendingConstants],
3765                 &pending_32_bit_constants_[0]);
3766     }
3767     ConstantPoolEntry entry(position, value, sharing_ok);
3768     pending_32_bit_constants_[num_pending_32_bit_constants_++] = entry;
3769 
3770     // Make sure the constant pool is not emitted in place of the next
3771     // instruction for which we just recorded relocation info.
3772     BlockConstPoolFor(1);
3773     return ConstantPoolEntry::REGULAR;
3774   }
3775 }
3776 
3777 
ConstantPoolAddEntry(int position,double value)3778 ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
3779                                                           double value) {
3780   if (FLAG_enable_embedded_constant_pool) {
3781     return constant_pool_builder_.AddEntry(position, value);
3782   } else {
3783     DCHECK(num_pending_64_bit_constants_ < kMaxNumPending64Constants);
3784     if (num_pending_64_bit_constants_ == 0) {
3785       first_const_pool_64_use_ = position;
3786     } else if (num_pending_64_bit_constants_ == kMinNumPendingConstants &&
3787                pending_64_bit_constants_ ==
3788                    &pending_64_bit_constants_buffer_[0]) {
3789       // Inline buffer is full, switch to dynamically allocated buffer.
3790       pending_64_bit_constants_ =
3791           new ConstantPoolEntry[kMaxNumPending64Constants];
3792       std::copy(&pending_64_bit_constants_buffer_[0],
3793                 &pending_64_bit_constants_buffer_[kMinNumPendingConstants],
3794                 &pending_64_bit_constants_[0]);
3795     }
3796     ConstantPoolEntry entry(position, value);
3797     pending_64_bit_constants_[num_pending_64_bit_constants_++] = entry;
3798 
3799     // Make sure the constant pool is not emitted in place of the next
3800     // instruction for which we just recorded relocation info.
3801     BlockConstPoolFor(1);
3802     return ConstantPoolEntry::REGULAR;
3803   }
3804 }
3805 
3806 
BlockConstPoolFor(int instructions)3807 void Assembler::BlockConstPoolFor(int instructions) {
3808   if (FLAG_enable_embedded_constant_pool) {
3809     // Should be a no-op if using an embedded constant pool.
3810     DCHECK(num_pending_32_bit_constants_ == 0);
3811     DCHECK(num_pending_64_bit_constants_ == 0);
3812     return;
3813   }
3814 
3815   int pc_limit = pc_offset() + instructions * kInstrSize;
3816   if (no_const_pool_before_ < pc_limit) {
3817     // Max pool start (if we need a jump and an alignment).
3818 #ifdef DEBUG
3819     int start = pc_limit + kInstrSize + 2 * kPointerSize;
3820     DCHECK((num_pending_32_bit_constants_ == 0) ||
3821            (start - first_const_pool_32_use_ +
3822                 num_pending_64_bit_constants_ * kDoubleSize <
3823             kMaxDistToIntPool));
3824     DCHECK((num_pending_64_bit_constants_ == 0) ||
3825            (start - first_const_pool_64_use_ < kMaxDistToFPPool));
3826 #endif
3827     no_const_pool_before_ = pc_limit;
3828   }
3829 
3830   if (next_buffer_check_ < no_const_pool_before_) {
3831     next_buffer_check_ = no_const_pool_before_;
3832   }
3833 }
3834 
3835 
CheckConstPool(bool force_emit,bool require_jump)3836 void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
3837   if (FLAG_enable_embedded_constant_pool) {
3838     // Should be a no-op if using an embedded constant pool.
3839     DCHECK(num_pending_32_bit_constants_ == 0);
3840     DCHECK(num_pending_64_bit_constants_ == 0);
3841     return;
3842   }
3843 
3844   // Some short sequence of instruction mustn't be broken up by constant pool
3845   // emission, such sequences are protected by calls to BlockConstPoolFor and
3846   // BlockConstPoolScope.
3847   if (is_const_pool_blocked()) {
3848     // Something is wrong if emission is forced and blocked at the same time.
3849     DCHECK(!force_emit);
3850     return;
3851   }
3852 
3853   // There is nothing to do if there are no pending constant pool entries.
3854   if ((num_pending_32_bit_constants_ == 0) &&
3855       (num_pending_64_bit_constants_ == 0)) {
3856     // Calculate the offset of the next check.
3857     next_buffer_check_ = pc_offset() + kCheckPoolInterval;
3858     return;
3859   }
3860 
3861   // Check that the code buffer is large enough before emitting the constant
3862   // pool (include the jump over the pool and the constant pool marker and
3863   // the gap to the relocation information).
3864   int jump_instr = require_jump ? kInstrSize : 0;
3865   int size_up_to_marker = jump_instr + kInstrSize;
3866   int estimated_size_after_marker =
3867       num_pending_32_bit_constants_ * kPointerSize;
3868   bool has_int_values = (num_pending_32_bit_constants_ > 0);
3869   bool has_fp_values = (num_pending_64_bit_constants_ > 0);
3870   bool require_64_bit_align = false;
3871   if (has_fp_values) {
3872     require_64_bit_align =
3873         !IsAligned(reinterpret_cast<intptr_t>(pc_ + size_up_to_marker),
3874                    kDoubleAlignment);
3875     if (require_64_bit_align) {
3876       estimated_size_after_marker += kInstrSize;
3877     }
3878     estimated_size_after_marker += num_pending_64_bit_constants_ * kDoubleSize;
3879   }
3880   int estimated_size = size_up_to_marker + estimated_size_after_marker;
3881 
3882   // We emit a constant pool when:
3883   //  * requested to do so by parameter force_emit (e.g. after each function).
3884   //  * the distance from the first instruction accessing the constant pool to
3885   //    any of the constant pool entries will exceed its limit the next
3886   //    time the pool is checked. This is overly restrictive, but we don't emit
3887   //    constant pool entries in-order so it's conservatively correct.
3888   //  * the instruction doesn't require a jump after itself to jump over the
3889   //    constant pool, and we're getting close to running out of range.
3890   if (!force_emit) {
3891     DCHECK(has_fp_values || has_int_values);
3892     bool need_emit = false;
3893     if (has_fp_values) {
3894       // The 64-bit constants are always emitted before the 32-bit constants, so
3895       // we can ignore the effect of the 32-bit constants on estimated_size.
3896       int dist64 = pc_offset() + estimated_size -
3897                    num_pending_32_bit_constants_ * kPointerSize -
3898                    first_const_pool_64_use_;
3899       if ((dist64 >= kMaxDistToFPPool - kCheckPoolInterval) ||
3900           (!require_jump && (dist64 >= kMaxDistToFPPool / 2))) {
3901         need_emit = true;
3902       }
3903     }
3904     if (has_int_values) {
3905       int dist32 = pc_offset() + estimated_size - first_const_pool_32_use_;
3906       if ((dist32 >= kMaxDistToIntPool - kCheckPoolInterval) ||
3907           (!require_jump && (dist32 >= kMaxDistToIntPool / 2))) {
3908         need_emit = true;
3909       }
3910     }
3911     if (!need_emit) return;
3912   }
3913 
3914   // Deduplicate constants.
3915   int size_after_marker = estimated_size_after_marker;
3916   for (int i = 0; i < num_pending_64_bit_constants_; i++) {
3917     ConstantPoolEntry& entry = pending_64_bit_constants_[i];
3918     DCHECK(!entry.is_merged());
3919     for (int j = 0; j < i; j++) {
3920       if (entry.value64() == pending_64_bit_constants_[j].value64()) {
3921         DCHECK(!pending_64_bit_constants_[j].is_merged());
3922         entry.set_merged_index(j);
3923         size_after_marker -= kDoubleSize;
3924         break;
3925       }
3926     }
3927   }
3928 
3929   for (int i = 0; i < num_pending_32_bit_constants_; i++) {
3930     ConstantPoolEntry& entry = pending_32_bit_constants_[i];
3931     DCHECK(!entry.is_merged());
3932     if (!entry.sharing_ok()) continue;
3933     for (int j = 0; j < i; j++) {
3934       if (entry.value() == pending_32_bit_constants_[j].value()) {
3935         DCHECK(!pending_32_bit_constants_[j].is_merged());
3936         entry.set_merged_index(j);
3937         size_after_marker -= kPointerSize;
3938         break;
3939       }
3940     }
3941   }
3942 
3943   int size = size_up_to_marker + size_after_marker;
3944 
3945   int needed_space = size + kGap;
3946   while (buffer_space() <= needed_space) GrowBuffer();
3947 
3948   {
3949     // Block recursive calls to CheckConstPool.
3950     BlockConstPoolScope block_const_pool(this);
3951     RecordComment("[ Constant Pool");
3952     RecordConstPool(size);
3953 
3954     Label size_check;
3955     bind(&size_check);
3956 
3957     // Emit jump over constant pool if necessary.
3958     Label after_pool;
3959     if (require_jump) {
3960       b(&after_pool);
3961     }
3962 
3963     // Put down constant pool marker "Undefined instruction".
3964     // The data size helps disassembly know what to print.
3965     emit(kConstantPoolMarker |
3966          EncodeConstantPoolLength(size_after_marker / kPointerSize));
3967 
3968     if (require_64_bit_align) {
3969       emit(kConstantPoolMarker);
3970     }
3971 
3972     // Emit 64-bit constant pool entries first: their range is smaller than
3973     // 32-bit entries.
3974     for (int i = 0; i < num_pending_64_bit_constants_; i++) {
3975       ConstantPoolEntry& entry = pending_64_bit_constants_[i];
3976 
3977       Instr instr = instr_at(entry.position());
3978       // Instruction to patch must be 'vldr rd, [pc, #offset]' with offset == 0.
3979       DCHECK((IsVldrDPcImmediateOffset(instr) &&
3980               GetVldrDRegisterImmediateOffset(instr) == 0));
3981 
3982       int delta = pc_offset() - entry.position() - kPcLoadDelta;
3983       DCHECK(is_uint10(delta));
3984 
3985       if (entry.is_merged()) {
3986         ConstantPoolEntry& merged =
3987             pending_64_bit_constants_[entry.merged_index()];
3988         DCHECK(entry.value64() == merged.value64());
3989         Instr merged_instr = instr_at(merged.position());
3990         DCHECK(IsVldrDPcImmediateOffset(merged_instr));
3991         delta = GetVldrDRegisterImmediateOffset(merged_instr);
3992         delta += merged.position() - entry.position();
3993       }
3994       instr_at_put(entry.position(),
3995                    SetVldrDRegisterImmediateOffset(instr, delta));
3996       if (!entry.is_merged()) {
3997         DCHECK(IsAligned(reinterpret_cast<intptr_t>(pc_), kDoubleAlignment));
3998         dq(entry.value64());
3999       }
4000     }
4001 
4002     // Emit 32-bit constant pool entries.
4003     for (int i = 0; i < num_pending_32_bit_constants_; i++) {
4004       ConstantPoolEntry& entry = pending_32_bit_constants_[i];
4005       Instr instr = instr_at(entry.position());
4006 
4007       // 64-bit loads shouldn't get here.
4008       DCHECK(!IsVldrDPcImmediateOffset(instr));
4009       DCHECK(!IsMovW(instr));
4010       DCHECK(IsLdrPcImmediateOffset(instr) &&
4011              GetLdrRegisterImmediateOffset(instr) == 0);
4012 
4013       int delta = pc_offset() - entry.position() - kPcLoadDelta;
4014       DCHECK(is_uint12(delta));
4015       // 0 is the smallest delta:
4016       //   ldr rd, [pc, #0]
4017       //   constant pool marker
4018       //   data
4019 
4020       if (entry.is_merged()) {
4021         DCHECK(entry.sharing_ok());
4022         ConstantPoolEntry& merged =
4023             pending_32_bit_constants_[entry.merged_index()];
4024         DCHECK(entry.value() == merged.value());
4025         Instr merged_instr = instr_at(merged.position());
4026         DCHECK(IsLdrPcImmediateOffset(merged_instr));
4027         delta = GetLdrRegisterImmediateOffset(merged_instr);
4028         delta += merged.position() - entry.position();
4029       }
4030       instr_at_put(entry.position(),
4031                    SetLdrRegisterImmediateOffset(instr, delta));
4032       if (!entry.is_merged()) {
4033         emit(entry.value());
4034       }
4035     }
4036 
4037     num_pending_32_bit_constants_ = 0;
4038     num_pending_64_bit_constants_ = 0;
4039     first_const_pool_32_use_ = -1;
4040     first_const_pool_64_use_ = -1;
4041 
4042     RecordComment("]");
4043 
4044     DCHECK_EQ(size, SizeOfCodeGeneratedSince(&size_check));
4045 
4046     if (after_pool.is_linked()) {
4047       bind(&after_pool);
4048     }
4049   }
4050 
4051   // Since a constant pool was just emitted, move the check offset forward by
4052   // the standard interval.
4053   next_buffer_check_ = pc_offset() + kCheckPoolInterval;
4054 }
4055 
4056 
PatchConstantPoolAccessInstruction(int pc_offset,int offset,ConstantPoolEntry::Access access,ConstantPoolEntry::Type type)4057 void Assembler::PatchConstantPoolAccessInstruction(
4058     int pc_offset, int offset, ConstantPoolEntry::Access access,
4059     ConstantPoolEntry::Type type) {
4060   DCHECK(FLAG_enable_embedded_constant_pool);
4061   Address pc = buffer_ + pc_offset;
4062 
4063   // Patch vldr/ldr instruction with correct offset.
4064   Instr instr = instr_at(pc);
4065   if (access == ConstantPoolEntry::OVERFLOWED) {
4066     if (CpuFeatures::IsSupported(ARMv7)) {
4067       // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0].
4068       Instr next_instr = instr_at(pc + kInstrSize);
4069       DCHECK((IsMovW(instr) && Instruction::ImmedMovwMovtValue(instr) == 0));
4070       DCHECK((IsMovT(next_instr) &&
4071               Instruction::ImmedMovwMovtValue(next_instr) == 0));
4072       instr_at_put(pc, PatchMovwImmediate(instr, offset & 0xffff));
4073       instr_at_put(pc + kInstrSize,
4074                    PatchMovwImmediate(next_instr, offset >> 16));
4075     } else {
4076       // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0].
4077       Instr instr_2 = instr_at(pc + kInstrSize);
4078       Instr instr_3 = instr_at(pc + 2 * kInstrSize);
4079       Instr instr_4 = instr_at(pc + 3 * kInstrSize);
4080       DCHECK((IsMovImmed(instr) && Instruction::Immed8Value(instr) == 0));
4081       DCHECK((IsOrrImmed(instr_2) && Instruction::Immed8Value(instr_2) == 0) &&
4082              GetRn(instr_2).is(GetRd(instr_2)));
4083       DCHECK((IsOrrImmed(instr_3) && Instruction::Immed8Value(instr_3) == 0) &&
4084              GetRn(instr_3).is(GetRd(instr_3)));
4085       DCHECK((IsOrrImmed(instr_4) && Instruction::Immed8Value(instr_4) == 0) &&
4086              GetRn(instr_4).is(GetRd(instr_4)));
4087       instr_at_put(pc, PatchShiftImm(instr, (offset & kImm8Mask)));
4088       instr_at_put(pc + kInstrSize,
4089                    PatchShiftImm(instr_2, (offset & (kImm8Mask << 8))));
4090       instr_at_put(pc + 2 * kInstrSize,
4091                    PatchShiftImm(instr_3, (offset & (kImm8Mask << 16))));
4092       instr_at_put(pc + 3 * kInstrSize,
4093                    PatchShiftImm(instr_4, (offset & (kImm8Mask << 24))));
4094     }
4095   } else if (type == ConstantPoolEntry::DOUBLE) {
4096     // Instruction to patch must be 'vldr rd, [pp, #0]'.
4097     DCHECK((IsVldrDPpImmediateOffset(instr) &&
4098             GetVldrDRegisterImmediateOffset(instr) == 0));
4099     DCHECK(is_uint10(offset));
4100     instr_at_put(pc, SetVldrDRegisterImmediateOffset(instr, offset));
4101   } else {
4102     // Instruction to patch must be 'ldr rd, [pp, #0]'.
4103     DCHECK((IsLdrPpImmediateOffset(instr) &&
4104             GetLdrRegisterImmediateOffset(instr) == 0));
4105     DCHECK(is_uint12(offset));
4106     instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset));
4107   }
4108 }
4109 
4110 
4111 }  // namespace internal
4112 }  // namespace v8
4113 
4114 #endif  // V8_TARGET_ARCH_ARM
4115