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