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 // A light-weight ARM Assembler
38 // Generates user mode instructions for the ARM architecture up to version 5
39 
40 #ifndef V8_CODEGEN_ARM_ASSEMBLER_ARM_H_
41 #define V8_CODEGEN_ARM_ASSEMBLER_ARM_H_
42 
43 #include <stdio.h>
44 
45 #include <memory>
46 
47 #include "src/base/numbers/double.h"
48 #include "src/base/small-vector.h"
49 #include "src/codegen/arm/constants-arm.h"
50 #include "src/codegen/arm/register-arm.h"
51 #include "src/codegen/assembler.h"
52 #include "src/codegen/constant-pool.h"
53 #include "src/codegen/machine-type.h"
54 #include "src/utils/boxed-float.h"
55 
56 namespace v8 {
57 namespace internal {
58 
59 class SafepointTableBuilder;
60 
61 // Coprocessor number
62 enum Coprocessor {
63   p0 = 0,
64   p1 = 1,
65   p2 = 2,
66   p3 = 3,
67   p4 = 4,
68   p5 = 5,
69   p6 = 6,
70   p7 = 7,
71   p8 = 8,
72   p9 = 9,
73   p10 = 10,
74   p11 = 11,
75   p12 = 12,
76   p13 = 13,
77   p14 = 14,
78   p15 = 15
79 };
80 
81 // -----------------------------------------------------------------------------
82 // Machine instruction Operands
83 
84 // Class Operand represents a shifter operand in data processing instructions
85 class V8_EXPORT_PRIVATE Operand {
86  public:
87   // immediate
Operand(int32_t immediate, RelocInfo::Mode rmode = RelocInfo::NO_INFO)88   V8_INLINE explicit Operand(int32_t immediate,
89                              RelocInfo::Mode rmode = RelocInfo::NO_INFO)
90       : rmode_(rmode) {
91     value_.immediate = immediate;
92   }
93   V8_INLINE static Operand Zero();
94   V8_INLINE explicit Operand(const ExternalReference& f);
95   explicit Operand(Handle<HeapObject> handle);
96   V8_INLINE explicit Operand(Smi value);
97 
98   // rm
99   V8_INLINE explicit Operand(Register rm);
100 
101   // rm <shift_op> shift_imm
102   explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
SmiUntag(Register rm)103   V8_INLINE static Operand SmiUntag(Register rm) {
104     return Operand(rm, ASR, kSmiTagSize);
105   }
PointerOffsetFromSmiKey(Register key)106   V8_INLINE static Operand PointerOffsetFromSmiKey(Register key) {
107     STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
108     return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
109   }
DoubleOffsetFromSmiKey(Register key)110   V8_INLINE static Operand DoubleOffsetFromSmiKey(Register key) {
111     STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
112     return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
113   }
114 
115   // rm <shift_op> rs
116   explicit Operand(Register rm, ShiftOp shift_op, Register rs);
117 
118   static Operand EmbeddedNumber(double number);  // Smi or HeapNumber.
119   static Operand EmbeddedStringConstant(const StringConstantBase* str);
120 
121   // Return true if this is a register operand.
IsRegister() const122   bool IsRegister() const {
123     return rm_.is_valid() && rs_ == no_reg && shift_op_ == LSL &&
124            shift_imm_ == 0;
125   }
126   // Return true if this is a register operand shifted with an immediate.
IsImmediateShiftedRegister() const127   bool IsImmediateShiftedRegister() const {
128     return rm_.is_valid() && !rs_.is_valid();
129   }
130   // Return true if this is a register operand shifted with a register.
IsRegisterShiftedRegister() const131   bool IsRegisterShiftedRegister() const {
132     return rm_.is_valid() && rs_.is_valid();
133   }
134 
135   // Return the number of actual instructions required to implement the given
136   // instruction for this particular operand. This can be a single instruction,
137   // if no load into a scratch register is necessary, or anything between 2 and
138   // 4 instructions when we need to load from the constant pool (depending upon
139   // whether the constant pool entry is in the small or extended section). If
140   // the instruction this operand is used for is a MOV or MVN instruction the
141   // actual instruction to use is required for this calculation. For other
142   // instructions instr is ignored.
143   //
144   // The value returned is only valid as long as no entries are added to the
145   // constant pool between this call and the actual instruction being emitted.
146   int InstructionsRequired(const Assembler* assembler, Instr instr = 0) const;
147   bool MustOutputRelocInfo(const Assembler* assembler) const;
148 
immediate() const149   inline int32_t immediate() const {
150     DCHECK(IsImmediate());
151     DCHECK(!IsHeapObjectRequest());
152     return value_.immediate;
153   }
IsImmediate() const154   bool IsImmediate() const { return !rm_.is_valid(); }
155 
heap_object_request() const156   HeapObjectRequest heap_object_request() const {
157     DCHECK(IsHeapObjectRequest());
158     return value_.heap_object_request;
159   }
IsHeapObjectRequest() const160   bool IsHeapObjectRequest() const {
161     DCHECK_IMPLIES(is_heap_object_request_, IsImmediate());
162     DCHECK_IMPLIES(is_heap_object_request_,
163                    rmode_ == RelocInfo::FULL_EMBEDDED_OBJECT ||
164                        rmode_ == RelocInfo::CODE_TARGET);
165     return is_heap_object_request_;
166   }
167 
rm() const168   Register rm() const { return rm_; }
rs() const169   Register rs() const { return rs_; }
shift_op() const170   ShiftOp shift_op() const { return shift_op_; }
171 
172  private:
173   Register rm_ = no_reg;
174   Register rs_ = no_reg;
175   ShiftOp shift_op_;
176   int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
177   union Value {
Value()178     Value() {}
179     HeapObjectRequest heap_object_request;  // if is_heap_object_request_
180     int32_t immediate;                      // otherwise
181   } value_;                                 // valid if rm_ == no_reg
182   bool is_heap_object_request_ = false;
183   RelocInfo::Mode rmode_;
184 
185   friend class Assembler;
186 };
187 
188 // Class MemOperand represents a memory operand in load and store instructions
189 class V8_EXPORT_PRIVATE MemOperand {
190  public:
191   // [rn +/- offset]      Offset/NegOffset
192   // [rn +/- offset]!     PreIndex/NegPreIndex
193   // [rn], +/- offset     PostIndex/NegPostIndex
194   // offset is any signed 32-bit value; offset is first loaded to a scratch
195   // register if it does not fit the addressing mode (12-bit unsigned and sign
196   // bit)
197   explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
198 
199   // [rn +/- rm]          Offset/NegOffset
200   // [rn +/- rm]!         PreIndex/NegPreIndex
201   // [rn], +/- rm         PostIndex/NegPostIndex
202   explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
203 
204   // [rn +/- rm <shift_op> shift_imm]      Offset/NegOffset
205   // [rn +/- rm <shift_op> shift_imm]!     PreIndex/NegPreIndex
206   // [rn], +/- rm <shift_op> shift_imm     PostIndex/NegPostIndex
207   explicit MemOperand(Register rn, Register rm, ShiftOp shift_op, int shift_imm,
208                       AddrMode am = Offset);
PointerAddressFromSmiKey(Register array, Register key, AddrMode am = Offset)209   V8_INLINE static MemOperand PointerAddressFromSmiKey(Register array,
210                                                        Register key,
211                                                        AddrMode am = Offset) {
212     STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
213     return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
214   }
215 
set_offset(int32_t offset)216   void set_offset(int32_t offset) {
217     DCHECK(rm_ == no_reg);
218     offset_ = offset;
219   }
220 
offset() const221   uint32_t offset() const {
222     DCHECK(rm_ == no_reg);
223     return offset_;
224   }
225 
rn() const226   Register rn() const { return rn_; }
rm() const227   Register rm() const { return rm_; }
am() const228   AddrMode am() const { return am_; }
229 
OffsetIsUint12Encodable() const230   bool OffsetIsUint12Encodable() const {
231     return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
232   }
233 
234  private:
235   Register rn_;     // base
236   Register rm_;     // register offset
237   int32_t offset_;  // valid if rm_ == no_reg
238   ShiftOp shift_op_;
239   int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
240   AddrMode am_;    // bits P, U, and W
241 
242   friend class Assembler;
243 };
244 
245 // Class NeonMemOperand represents a memory operand in load and
246 // store NEON instructions
247 class V8_EXPORT_PRIVATE NeonMemOperand {
248  public:
249   // [rn {:align}]       Offset
250   // [rn {:align}]!      PostIndex
251   explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
252 
253   // [rn {:align}], rm   PostIndex
254   explicit NeonMemOperand(Register rn, Register rm, int align = 0);
255 
rn() const256   Register rn() const { return rn_; }
rm() const257   Register rm() const { return rm_; }
align() const258   int align() const { return align_; }
259 
260  private:
261   void SetAlignment(int align);
262 
263   Register rn_;  // base
264   Register rm_;  // register increment
265   int align_;
266 };
267 
268 // Class NeonListOperand represents a list of NEON registers
269 class NeonListOperand {
270  public:
NeonListOperand(DoubleRegister base, int register_count = 1)271   explicit NeonListOperand(DoubleRegister base, int register_count = 1)
272       : base_(base), register_count_(register_count) {}
NeonListOperand(QwNeonRegister q_reg)273   explicit NeonListOperand(QwNeonRegister q_reg)
274       : base_(q_reg.low()), register_count_(2) {}
base() const275   DoubleRegister base() const { return base_; }
register_count()276   int register_count() { return register_count_; }
length() const277   int length() const { return register_count_ - 1; }
type() const278   NeonListType type() const {
279     switch (register_count_) {
280       default:
281         UNREACHABLE();
282       // Fall through.
283       case 1:
284         return nlt_1;
285       case 2:
286         return nlt_2;
287       case 3:
288         return nlt_3;
289       case 4:
290         return nlt_4;
291     }
292   }
293 
294  private:
295   DoubleRegister base_;
296   int register_count_;
297 };
298 
299 class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
300  public:
301   // Create an assembler. Instructions and relocation information are emitted
302   // into a buffer, with the instructions starting from the beginning and the
303   // relocation information starting from the end of the buffer. See CodeDesc
304   // for a detailed comment on the layout (globals.h).
305   //
306   // If the provided buffer is nullptr, the assembler allocates and grows its
307   // own buffer. Otherwise it takes ownership of the provided buffer.
308   explicit Assembler(const AssemblerOptions&,
309                      std::unique_ptr<AssemblerBuffer> = {});
310 
311   ~Assembler() override;
312 
313   void AbortedCodeGeneration() override {
314     pending_32_bit_constants_.clear();
315     first_const_pool_32_use_ = -1;
316   }
317 
318   // GetCode emits any pending (non-emitted) code and fills the descriptor desc.
319   static constexpr int kNoHandlerTable = 0;
320   static constexpr SafepointTableBuilder* kNoSafepointTable = nullptr;
321   void GetCode(Isolate* isolate, CodeDesc* desc,
322                SafepointTableBuilder* safepoint_table_builder,
323                int handler_table_offset);
324 
325   // Convenience wrapper for code without safepoint or handler tables.
GetCode(Isolate* isolate, CodeDesc* desc)326   void GetCode(Isolate* isolate, CodeDesc* desc) {
327     GetCode(isolate, desc, kNoSafepointTable, kNoHandlerTable);
328   }
329 
330   // Label operations & relative jumps (PPUM Appendix D)
331   //
332   // Takes a branch opcode (cc) and a label (L) and generates
333   // either a backward branch or a forward branch and links it
334   // to the label fixup chain. Usage:
335   //
336   // Label L;    // unbound label
337   // j(cc, &L);  // forward branch to unbound label
338   // bind(&L);   // bind label to the current pc
339   // j(cc, &L);  // backward branch to bound label
340   // bind(&L);   // illegal: a label may be bound only once
341   //
342   // Note: The same Label can be used for forward and backward branches
343   // but it may be bound only once.
344 
345   void bind(Label* L);  // binds an unbound label L to the current code position
346 
347   // Returns the branch offset to the given label from the current code position
348   // Links the label to the current position if it is still unbound
349   // Manages the jump elimination optimization if the second parameter is true.
350   int branch_offset(Label* L);
351 
352   // Returns true if the given pc address is the start of a constant pool load
353   // instruction sequence.
354   V8_INLINE static bool is_constant_pool_load(Address pc);
355 
356   // Return the address in the constant pool of the code target address used by
357   // the branch/call instruction at pc, or the object in a mov.
358   V8_INLINE static Address constant_pool_entry_address(Address pc,
359                                                        Address constant_pool);
360 
361   // Read/Modify the code target address in the branch/call instruction at pc.
362   // The isolate argument is unused (and may be nullptr) when skipping flushing.
363   V8_INLINE static Address target_address_at(Address pc, Address constant_pool);
364   V8_INLINE static void set_target_address_at(
365       Address pc, Address constant_pool, Address target,
366       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
367 
368   // This sets the branch destination (which is in the constant pool on ARM).
369   // This is for calls and branches within generated code.
370   inline static void deserialization_set_special_target_at(
371       Address constant_pool_entry, Code code, Address target);
372 
373   // Get the size of the special target encoded at 'location'.
374   inline static int deserialization_special_target_size(Address location);
375 
376   // This sets the internal reference at the pc.
377   inline static void deserialization_set_target_internal_reference_at(
378       Address pc, Address target,
379       RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
380 
381   // Here we are patching the address in the constant pool, not the actual call
382   // instruction.  The address in the constant pool is the same size as a
383   // pointer.
384   static constexpr int kSpecialTargetSize = kPointerSize;
385 
GetScratchRegisterList()386   RegList* GetScratchRegisterList() { return &scratch_register_list_; }
GetScratchVfpRegisterList()387   VfpRegList* GetScratchVfpRegisterList() {
388     return &scratch_vfp_register_list_;
389   }
390 
391   // ---------------------------------------------------------------------------
392   // Code generation
393 
394   // Insert the smallest number of nop instructions
395   // possible to align the pc offset to a multiple
396   // of m. m must be a power of 2 (>= 4).
397   void Align(int m);
398   // Insert the smallest number of zero bytes possible to align the pc offset
399   // to a mulitple of m. m must be a power of 2 (>= 2).
400   void DataAlign(int m);
401   // Aligns code to something that's optimal for a jump target for the platform.
402   void CodeTargetAlign();
LoopHeaderAlign()403   void LoopHeaderAlign() { CodeTargetAlign(); }
404 
405   // Branch instructions
406   void b(int branch_offset, Condition cond = al,
407          RelocInfo::Mode rmode = RelocInfo::NO_INFO);
408   void bl(int branch_offset, Condition cond = al,
409           RelocInfo::Mode rmode = RelocInfo::NO_INFO);
410   void blx(int branch_offset);                     // v5 and above
411   void blx(Register target, Condition cond = al);  // v5 and above
412   void bx(Register target, Condition cond = al);   // v5 and above, plus v4t
413 
414   // Convenience branch instructions using labels
415   void b(Label* L, Condition cond = al);
b(Condition cond, Label* L)416   void b(Condition cond, Label* L) { b(L, cond); }
417   void bl(Label* L, Condition cond = al);
bl(Condition cond, Label* L)418   void bl(Condition cond, Label* L) { bl(L, cond); }
419   void blx(Label* L);  // v5 and above
420 
421   // Data-processing instructions
422 
423   void and_(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
424             Condition cond = al);
425   void and_(Register dst, Register src1, Register src2, SBit s = LeaveCC,
426             Condition cond = al);
427 
428   void eor(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
429            Condition cond = al);
430   void eor(Register dst, Register src1, Register src2, SBit s = LeaveCC,
431            Condition cond = al);
432 
433   void sub(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
434            Condition cond = al);
435   void sub(Register dst, Register src1, Register src2, SBit s = LeaveCC,
436            Condition cond = al);
437 
438   void rsb(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
439            Condition cond = al);
440 
441   void add(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
442            Condition cond = al);
443   void add(Register dst, Register src1, Register src2, SBit s = LeaveCC,
444            Condition cond = al);
445 
446   void adc(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
447            Condition cond = al);
448 
449   void sbc(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
450            Condition cond = al);
451 
452   void rsc(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
453            Condition cond = al);
454 
455   void tst(Register src1, const Operand& src2, Condition cond = al);
456   void tst(Register src1, Register src2, Condition cond = al);
457 
458   void teq(Register src1, const Operand& src2, Condition cond = al);
459 
460   void cmp(Register src1, const Operand& src2, Condition cond = al);
461   void cmp(Register src1, Register src2, Condition cond = al);
462 
463   void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
464 
465   void cmn(Register src1, const Operand& src2, Condition cond = al);
466 
467   void orr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
468            Condition cond = al);
469   void orr(Register dst, Register src1, Register src2, SBit s = LeaveCC,
470            Condition cond = al);
471 
472   void mov(Register dst, const Operand& src, SBit s = LeaveCC,
473            Condition cond = al);
474   void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al);
475 
476   // Load the position of the label relative to the generated code object
477   // pointer in a register.
478   void mov_label_offset(Register dst, Label* label);
479 
480   // ARMv7 instructions for loading a 32 bit immediate in two instructions.
481   // The constant for movw and movt should be in the range 0-0xffff.
482   void movw(Register reg, uint32_t immediate, Condition cond = al);
483   void movt(Register reg, uint32_t immediate, Condition cond = al);
484 
485   void bic(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
486            Condition cond = al);
487 
488   void mvn(Register dst, const Operand& src, SBit s = LeaveCC,
489            Condition cond = al);
490 
491   // Shift instructions
492 
493   void asr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
494            Condition cond = al);
495 
496   void lsl(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
497            Condition cond = al);
498 
499   void lsr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
500            Condition cond = al);
501 
502   // Multiply instructions
503 
504   void mla(Register dst, Register src1, Register src2, Register srcA,
505            SBit s = LeaveCC, Condition cond = al);
506 
507   void mls(Register dst, Register src1, Register src2, Register srcA,
508            Condition cond = al);
509 
510   void sdiv(Register dst, Register src1, Register src2, Condition cond = al);
511 
512   void udiv(Register dst, Register src1, Register src2, Condition cond = al);
513 
514   void mul(Register dst, Register src1, Register src2, SBit s = LeaveCC,
515            Condition cond = al);
516 
517   void smmla(Register dst, Register src1, Register src2, Register srcA,
518              Condition cond = al);
519 
520   void smmul(Register dst, Register src1, Register src2, Condition cond = al);
521 
522   void smlal(Register dstL, Register dstH, Register src1, Register src2,
523              SBit s = LeaveCC, Condition cond = al);
524 
525   void smull(Register dstL, Register dstH, Register src1, Register src2,
526              SBit s = LeaveCC, Condition cond = al);
527 
528   void umlal(Register dstL, Register dstH, Register src1, Register src2,
529              SBit s = LeaveCC, Condition cond = al);
530 
531   void umull(Register dstL, Register dstH, Register src1, Register src2,
532              SBit s = LeaveCC, Condition cond = al);
533 
534   // Miscellaneous arithmetic instructions
535 
536   void clz(Register dst, Register src, Condition cond = al);  // v5 and above
537 
538   // Saturating instructions. v6 and above.
539 
540   // Unsigned saturate.
541   //
542   // Saturate an optionally shifted signed value to an unsigned range.
543   //
544   //   usat dst, #satpos, src
545   //   usat dst, #satpos, src, lsl #sh
546   //   usat dst, #satpos, src, asr #sh
547   //
548   // Register dst will contain:
549   //
550   //   0,                 if s < 0
551   //   (1 << satpos) - 1, if s > ((1 << satpos) - 1)
552   //   s,                 otherwise
553   //
554   // where s is the contents of src after shifting (if used.)
555   void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
556 
557   // Bitfield manipulation instructions. v7 and above.
558 
559   void ubfx(Register dst, Register src, int lsb, int width,
560             Condition cond = al);
561 
562   void sbfx(Register dst, Register src, int lsb, int width,
563             Condition cond = al);
564 
565   void bfc(Register dst, int lsb, int width, Condition cond = al);
566 
567   void bfi(Register dst, Register src, int lsb, int width, Condition cond = al);
568 
569   void pkhbt(Register dst, Register src1, const Operand& src2,
570              Condition cond = al);
571 
572   void pkhtb(Register dst, Register src1, const Operand& src2,
573              Condition cond = al);
574 
575   void sxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
576   void sxtab(Register dst, Register src1, Register src2, int rotate = 0,
577              Condition cond = al);
578   void sxth(Register dst, Register src, int rotate = 0, Condition cond = al);
579   void sxtah(Register dst, Register src1, Register src2, int rotate = 0,
580              Condition cond = al);
581 
582   void uxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
583   void uxtab(Register dst, Register src1, Register src2, int rotate = 0,
584              Condition cond = al);
585   void uxtb16(Register dst, Register src, int rotate = 0, Condition cond = al);
586   void uxth(Register dst, Register src, int rotate = 0, Condition cond = al);
587   void uxtah(Register dst, Register src1, Register src2, int rotate = 0,
588              Condition cond = al);
589 
590   // Reverse the bits in a register.
591   void rbit(Register dst, Register src, Condition cond = al);
592   void rev(Register dst, Register src, Condition cond = al);
593 
594   // Status register access instructions
595 
596   void mrs(Register dst, SRegister s, Condition cond = al);
597   void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
598 
599   // Load/Store instructions
600   void ldr(Register dst, const MemOperand& src, Condition cond = al);
601   void str(Register src, const MemOperand& dst, Condition cond = al);
602   void ldrb(Register dst, const MemOperand& src, Condition cond = al);
603   void strb(Register src, const MemOperand& dst, Condition cond = al);
604   void ldrh(Register dst, const MemOperand& src, Condition cond = al);
605   void strh(Register src, const MemOperand& dst, Condition cond = al);
606   void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
607   void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
608   void ldrd(Register dst1, Register dst2, const MemOperand& src,
609             Condition cond = al);
610   void strd(Register src1, Register src2, const MemOperand& dst,
611             Condition cond = al);
612 
613   // Load literal from a pc relative address.
614   void ldr_pcrel(Register dst, int imm12, Condition cond = al);
615 
616   // Load/Store exclusive instructions
617   void ldrex(Register dst, Register src, Condition cond = al);
618   void strex(Register src1, Register src2, Register dst, Condition cond = al);
619   void ldrexb(Register dst, Register src, Condition cond = al);
620   void strexb(Register src1, Register src2, Register dst, Condition cond = al);
621   void ldrexh(Register dst, Register src, Condition cond = al);
622   void strexh(Register src1, Register src2, Register dst, Condition cond = al);
623   void ldrexd(Register dst1, Register dst2, Register src, Condition cond = al);
624   void strexd(Register res, Register src1, Register src2, Register dst,
625               Condition cond = al);
626 
627   // Preload instructions
628   void pld(const MemOperand& address);
629 
630   // Load/Store multiple instructions
631   void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
632   void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
633 
634   // Exception-generating instructions and debugging support
635   void stop(Condition cond = al, int32_t code = kDefaultStopCode);
636 
637   void bkpt(uint32_t imm16);  // v5 and above
638   void svc(uint32_t imm24, Condition cond = al);
639 
640   // Synchronization instructions.
641   // On ARMv6, an equivalent CP15 operation will be used.
642   void dmb(BarrierOption option);
643   void dsb(BarrierOption option);
644   void isb(BarrierOption option);
645 
646   // Conditional speculation barrier.
647   void csdb();
648 
649   // Coprocessor instructions
650 
651   void cdp(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn,
652            CRegister crm, int opcode_2, Condition cond = al);
653 
654   void cdp2(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn,
655             CRegister crm,
656             int opcode_2);  // v5 and above
657 
658   void mcr(Coprocessor coproc, int opcode_1, Register rd, CRegister crn,
659            CRegister crm, int opcode_2 = 0, Condition cond = al);
660 
661   void mcr2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn,
662             CRegister crm,
663             int opcode_2 = 0);  // v5 and above
664 
665   void mrc(Coprocessor coproc, int opcode_1, Register rd, CRegister crn,
666            CRegister crm, int opcode_2 = 0, Condition cond = al);
667 
668   void mrc2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn,
669             CRegister crm,
670             int opcode_2 = 0);  // v5 and above
671 
672   void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
673            LFlag l = Short, Condition cond = al);
674   void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
675            LFlag l = Short, Condition cond = al);
676 
677   void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
678             LFlag l = Short);  // v5 and above
679   void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
680             LFlag l = Short);  // v5 and above
681 
682   // Support for VFP.
683   // All these APIs support S0 to S31 and D0 to D31.
684 
685   void vldr(const DwVfpRegister dst, const Register base, int offset,
686             const Condition cond = al);
687   void vldr(const DwVfpRegister dst, const MemOperand& src,
688             const Condition cond = al);
689 
690   void vldr(const SwVfpRegister dst, const Register base, int offset,
691             const Condition cond = al);
692   void vldr(const SwVfpRegister dst, const MemOperand& src,
693             const Condition cond = al);
694 
695   void vstr(const DwVfpRegister src, const Register base, int offset,
696             const Condition cond = al);
697   void vstr(const DwVfpRegister src, const MemOperand& dst,
698             const Condition cond = al);
699 
700   void vstr(const SwVfpRegister src, const Register base, int offset,
701             const Condition cond = al);
702   void vstr(const SwVfpRegister src, const MemOperand& dst,
703             const Condition cond = al);
704 
705   void vldm(BlockAddrMode am, Register base, DwVfpRegister first,
706             DwVfpRegister last, Condition cond = al);
707 
708   void vstm(BlockAddrMode am, Register base, DwVfpRegister first,
709             DwVfpRegister last, Condition cond = al);
710 
711   void vldm(BlockAddrMode am, Register base, SwVfpRegister first,
712             SwVfpRegister last, Condition cond = al);
713 
714   void vstm(BlockAddrMode am, Register base, SwVfpRegister first,
715             SwVfpRegister last, Condition cond = al);
716 
717   void vmov(const SwVfpRegister dst, Float32 imm);
718   void vmov(const DwVfpRegister dst, base::Double imm,
719             const Register extra_scratch = no_reg);
720   void vmov(const SwVfpRegister dst, const SwVfpRegister src,
721             const Condition cond = al);
722   void vmov(const DwVfpRegister dst, const DwVfpRegister src,
723             const Condition cond = al);
724   void vmov(const DwVfpRegister dst, const Register src1, const Register src2,
725             const Condition cond = al);
726   void vmov(const Register dst1, const Register dst2, const DwVfpRegister src,
727             const Condition cond = al);
728   void vmov(const SwVfpRegister dst, const Register src,
729             const Condition cond = al);
730   void vmov(const Register dst, const SwVfpRegister src,
731             const Condition cond = al);
732   void vcvt_f64_s32(const DwVfpRegister dst, const SwVfpRegister src,
733                     VFPConversionMode mode = kDefaultRoundToZero,
734                     const Condition cond = al);
735   void vcvt_f32_s32(const SwVfpRegister dst, const SwVfpRegister src,
736                     VFPConversionMode mode = kDefaultRoundToZero,
737                     const Condition cond = al);
738   void vcvt_f64_u32(const DwVfpRegister dst, const SwVfpRegister src,
739                     VFPConversionMode mode = kDefaultRoundToZero,
740                     const Condition cond = al);
741   void vcvt_f32_u32(const SwVfpRegister dst, const SwVfpRegister src,
742                     VFPConversionMode mode = kDefaultRoundToZero,
743                     const Condition cond = al);
744   void vcvt_s32_f32(const SwVfpRegister dst, const SwVfpRegister src,
745                     VFPConversionMode mode = kDefaultRoundToZero,
746                     const Condition cond = al);
747   void vcvt_u32_f32(const SwVfpRegister dst, const SwVfpRegister src,
748                     VFPConversionMode mode = kDefaultRoundToZero,
749                     const Condition cond = al);
750   void vcvt_s32_f64(const SwVfpRegister dst, const DwVfpRegister src,
751                     VFPConversionMode mode = kDefaultRoundToZero,
752                     const Condition cond = al);
753   void vcvt_u32_f64(const SwVfpRegister dst, const DwVfpRegister src,
754                     VFPConversionMode mode = kDefaultRoundToZero,
755                     const Condition cond = al);
756   void vcvt_f64_f32(const DwVfpRegister dst, const SwVfpRegister src,
757                     VFPConversionMode mode = kDefaultRoundToZero,
758                     const Condition cond = al);
759   void vcvt_f32_f64(const SwVfpRegister dst, const DwVfpRegister src,
760                     VFPConversionMode mode = kDefaultRoundToZero,
761                     const Condition cond = al);
762   void vcvt_f64_s32(const DwVfpRegister dst, int fraction_bits,
763                     const Condition cond = al);
764 
765   void vmrs(const Register dst, const Condition cond = al);
766   void vmsr(const Register dst, const Condition cond = al);
767 
768   void vneg(const DwVfpRegister dst, const DwVfpRegister src,
769             const Condition cond = al);
770   void vneg(const SwVfpRegister dst, const SwVfpRegister src,
771             const Condition cond = al);
772   void vabs(const DwVfpRegister dst, const DwVfpRegister src,
773             const Condition cond = al);
774   void vabs(const SwVfpRegister dst, const SwVfpRegister src,
775             const Condition cond = al);
776   void vadd(const DwVfpRegister dst, const DwVfpRegister src1,
777             const DwVfpRegister src2, const Condition cond = al);
778   void vadd(const SwVfpRegister dst, const SwVfpRegister src1,
779             const SwVfpRegister src2, const Condition cond = al);
780   void vsub(const DwVfpRegister dst, const DwVfpRegister src1,
781             const DwVfpRegister src2, const Condition cond = al);
782   void vsub(const SwVfpRegister dst, const SwVfpRegister src1,
783             const SwVfpRegister src2, const Condition cond = al);
784   void vmul(const DwVfpRegister dst, const DwVfpRegister src1,
785             const DwVfpRegister src2, const Condition cond = al);
786   void vmul(const SwVfpRegister dst, const SwVfpRegister src1,
787             const SwVfpRegister src2, const Condition cond = al);
788   void vmla(const DwVfpRegister dst, const DwVfpRegister src1,
789             const DwVfpRegister src2, const Condition cond = al);
790   void vmla(const SwVfpRegister dst, const SwVfpRegister src1,
791             const SwVfpRegister src2, const Condition cond = al);
792   void vmls(const DwVfpRegister dst, const DwVfpRegister src1,
793             const DwVfpRegister src2, const Condition cond = al);
794   void vmls(const SwVfpRegister dst, const SwVfpRegister src1,
795             const SwVfpRegister src2, const Condition cond = al);
796   void vdiv(const DwVfpRegister dst, const DwVfpRegister src1,
797             const DwVfpRegister src2, const Condition cond = al);
798   void vdiv(const SwVfpRegister dst, const SwVfpRegister src1,
799             const SwVfpRegister src2, const Condition cond = al);
800   void vcmp(const DwVfpRegister src1, const DwVfpRegister src2,
801             const Condition cond = al);
802   void vcmp(const SwVfpRegister src1, const SwVfpRegister src2,
803             const Condition cond = al);
804   void vcmp(const DwVfpRegister src1, const double src2,
805             const Condition cond = al);
806   void vcmp(const SwVfpRegister src1, const float src2,
807             const Condition cond = al);
808 
809   void vmaxnm(const DwVfpRegister dst, const DwVfpRegister src1,
810               const DwVfpRegister src2);
811   void vmaxnm(const SwVfpRegister dst, const SwVfpRegister src1,
812               const SwVfpRegister src2);
813   void vminnm(const DwVfpRegister dst, const DwVfpRegister src1,
814               const DwVfpRegister src2);
815   void vminnm(const SwVfpRegister dst, const SwVfpRegister src1,
816               const SwVfpRegister src2);
817 
818   // VSEL supports cond in {eq, ne, ge, lt, gt, le, vs, vc}.
819   void vsel(const Condition cond, const DwVfpRegister dst,
820             const DwVfpRegister src1, const DwVfpRegister src2);
821   void vsel(const Condition cond, const SwVfpRegister dst,
822             const SwVfpRegister src1, const SwVfpRegister src2);
823 
824   void vsqrt(const DwVfpRegister dst, const DwVfpRegister src,
825              const Condition cond = al);
826   void vsqrt(const SwVfpRegister dst, const SwVfpRegister src,
827              const Condition cond = al);
828 
829   // ARMv8 rounding instructions (Scalar).
830   void vrinta(const SwVfpRegister dst, const SwVfpRegister src);
831   void vrinta(const DwVfpRegister dst, const DwVfpRegister src);
832   void vrintn(const SwVfpRegister dst, const SwVfpRegister src);
833   void vrintn(const DwVfpRegister dst, const DwVfpRegister src);
834   void vrintm(const SwVfpRegister dst, const SwVfpRegister src);
835   void vrintm(const DwVfpRegister dst, const DwVfpRegister src);
836   void vrintp(const SwVfpRegister dst, const SwVfpRegister src);
837   void vrintp(const DwVfpRegister dst, const DwVfpRegister src);
838   void vrintz(const SwVfpRegister dst, const SwVfpRegister src,
839               const Condition cond = al);
840   void vrintz(const DwVfpRegister dst, const DwVfpRegister src,
841               const Condition cond = al);
842 
843   // Support for NEON.
844 
845   // All these APIs support D0 to D31 and Q0 to Q15.
846   void vld1(NeonSize size, const NeonListOperand& dst,
847             const NeonMemOperand& src);
848   // vld1s(ingle element to one lane).
849   void vld1s(NeonSize size, const NeonListOperand& dst, uint8_t index,
850              const NeonMemOperand& src);
851   void vld1r(NeonSize size, const NeonListOperand& dst,
852              const NeonMemOperand& src);
853   void vst1(NeonSize size, const NeonListOperand& src,
854             const NeonMemOperand& dst);
855   // vst1s(single element from one lane).
856   void vst1s(NeonSize size, const NeonListOperand& src, uint8_t index,
857              const NeonMemOperand& dst);
858   // dt represents the narrower type
859   void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
860   // dst_dt represents the narrower type, src_dt represents the src type.
861   void vqmovn(NeonDataType dst_dt, NeonDataType src_dt, DwVfpRegister dst,
862               QwNeonRegister src);
863 
864   // Only unconditional core <-> scalar moves are currently supported.
865   void vmov(NeonDataType dt, DwVfpRegister dst, int index, Register src);
866   void vmov(NeonDataType dt, Register dst, DwVfpRegister src, int index);
867 
868   void vmov(DwVfpRegister dst, uint64_t imm);
869   void vmov(QwNeonRegister dst, uint64_t imm);
870   void vmov(QwNeonRegister dst, QwNeonRegister src);
871   void vdup(NeonSize size, QwNeonRegister dst, Register src);
872   void vdup(NeonSize size, QwNeonRegister dst, DwVfpRegister src, int index);
873   void vdup(NeonSize size, DwVfpRegister dst, DwVfpRegister src, int index);
874 
875   void vcvt_f32_s32(QwNeonRegister dst, QwNeonRegister src);
876   void vcvt_f32_u32(QwNeonRegister dst, QwNeonRegister src);
877   void vcvt_s32_f32(QwNeonRegister dst, QwNeonRegister src);
878   void vcvt_u32_f32(QwNeonRegister dst, QwNeonRegister src);
879 
880   void vmvn(QwNeonRegister dst, QwNeonRegister src);
881   void vswp(DwVfpRegister dst, DwVfpRegister src);
882   void vswp(QwNeonRegister dst, QwNeonRegister src);
883   void vabs(QwNeonRegister dst, QwNeonRegister src);
884   void vabs(NeonSize size, QwNeonRegister dst, QwNeonRegister src);
885   void vneg(QwNeonRegister dst, QwNeonRegister src);
886   void vneg(NeonSize size, QwNeonRegister dst, QwNeonRegister src);
887 
888   void vand(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
889   void vbic(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
890   void veor(DwVfpRegister dst, DwVfpRegister src1, DwVfpRegister src2);
891   void veor(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
892   void vbsl(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
893   void vorr(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
894   void vorn(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
895   void vadd(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
896   void vadd(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
897             QwNeonRegister src2);
898   void vqadd(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
899              QwNeonRegister src2);
900   void vsub(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
901   void vsub(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
902             QwNeonRegister src2);
903   void vqsub(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
904              QwNeonRegister src2);
905   void vmlal(NeonDataType size, QwNeonRegister dst, DwVfpRegister src1,
906              DwVfpRegister src2);
907   void vmul(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
908   void vmul(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
909             QwNeonRegister src2);
910   void vmull(NeonDataType size, QwNeonRegister dst, DwVfpRegister src1,
911              DwVfpRegister src2);
912   void vmin(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
913   void vmin(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
914             QwNeonRegister src2);
915   void vmax(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
916   void vmax(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
917             QwNeonRegister src2);
918   void vpadd(DwVfpRegister dst, DwVfpRegister src1, DwVfpRegister src2);
919   void vpadd(NeonSize size, DwVfpRegister dst, DwVfpRegister src1,
920              DwVfpRegister src2);
921   void vpmin(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src1,
922              DwVfpRegister src2);
923   void vpmax(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src1,
924              DwVfpRegister src2);
925 
926   void vpadal(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src);
927   void vpaddl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src);
928   void vqrdmulh(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
929                 QwNeonRegister src2);
930 
931   // ARMv8 rounding instructions (NEON).
932   void vrintm(NeonDataType dt, const QwNeonRegister dst,
933               const QwNeonRegister src);
934   void vrintn(NeonDataType dt, const QwNeonRegister dst,
935               const QwNeonRegister src);
936   void vrintp(NeonDataType dt, const QwNeonRegister dst,
937               const QwNeonRegister src);
938   void vrintz(NeonDataType dt, const QwNeonRegister dst,
939               const QwNeonRegister src);
940 
941   void vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src, int shift);
942   void vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
943             QwNeonRegister shift);
944   void vshr(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src, int shift);
945   void vshr(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src, int shift);
946   void vsli(NeonSize size, DwVfpRegister dst, DwVfpRegister src, int shift);
947   void vsri(NeonSize size, DwVfpRegister dst, DwVfpRegister src, int shift);
948   void vsra(NeonDataType size, DwVfpRegister dst, DwVfpRegister src, int imm);
949 
950   // vrecpe and vrsqrte only support floating point lanes.
951   void vrecpe(QwNeonRegister dst, QwNeonRegister src);
952   void vrsqrte(QwNeonRegister dst, QwNeonRegister src);
953   void vrecps(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
954   void vrsqrts(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
955   void vtst(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
956             QwNeonRegister src2);
957   void vceq(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
958   void vceq(NeonSize size, QwNeonRegister dst, QwNeonRegister src1,
959             QwNeonRegister src2);
960   void vceq(NeonSize size, QwNeonRegister dst, QwNeonRegister src, int value);
961   void vcge(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
962   void vcge(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
963             QwNeonRegister src2);
964   void vcgt(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
965   void vcgt(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
966             QwNeonRegister src2);
967   void vclt(NeonSize size, QwNeonRegister dst, QwNeonRegister src, int value);
968   void vrhadd(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
969               QwNeonRegister src2);
970   void vext(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2,
971             int bytes);
972   void vzip(NeonSize size, DwVfpRegister src1, DwVfpRegister src2);
973   void vzip(NeonSize size, QwNeonRegister src1, QwNeonRegister src2);
974   void vuzp(NeonSize size, DwVfpRegister src1, DwVfpRegister src2);
975   void vuzp(NeonSize size, QwNeonRegister src1, QwNeonRegister src2);
976   void vrev16(NeonSize size, QwNeonRegister dst, QwNeonRegister src);
977   void vrev32(NeonSize size, QwNeonRegister dst, QwNeonRegister src);
978   void vrev64(NeonSize size, QwNeonRegister dst, QwNeonRegister src);
979   void vtrn(NeonSize size, DwVfpRegister src1, DwVfpRegister src2);
980   void vtrn(NeonSize size, QwNeonRegister src1, QwNeonRegister src2);
981   void vtbl(DwVfpRegister dst, const NeonListOperand& list,
982             DwVfpRegister index);
983   void vtbx(DwVfpRegister dst, const NeonListOperand& list,
984             DwVfpRegister index);
985 
986   void vcnt(QwNeonRegister dst, QwNeonRegister src);
987 
988   // Pseudo instructions
989 
990   // Different nop operations are used by the code generator to detect certain
991   // states of the generated code.
992   enum NopMarkerTypes {
993     NON_MARKING_NOP = 0,
994     DEBUG_BREAK_NOP,
995     // IC markers.
996     PROPERTY_ACCESS_INLINED,
997     PROPERTY_ACCESS_INLINED_CONTEXT,
998     PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
999     // Helper values.
1000     LAST_CODE_MARKER,
1001     FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1002   };
1003 
1004   void nop(int type = 0);  // 0 is the default non-marking type.
1005 
push(Register src, Condition cond = al)1006   void push(Register src, Condition cond = al) {
1007     str(src, MemOperand(sp, 4, NegPreIndex), cond);
1008   }
1009 
pop(Register dst, Condition cond = al)1010   void pop(Register dst, Condition cond = al) {
1011     ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1012   }
1013 
1014   void pop();
1015 
vpush(QwNeonRegister src, Condition cond = al)1016   void vpush(QwNeonRegister src, Condition cond = al) {
1017     vstm(db_w, sp, src.low(), src.high(), cond);
1018   }
1019 
vpush(DwVfpRegister src, Condition cond = al)1020   void vpush(DwVfpRegister src, Condition cond = al) {
1021     vstm(db_w, sp, src, src, cond);
1022   }
1023 
vpush(SwVfpRegister src, Condition cond = al)1024   void vpush(SwVfpRegister src, Condition cond = al) {
1025     vstm(db_w, sp, src, src, cond);
1026   }
1027 
vpop(DwVfpRegister dst, Condition cond = al)1028   void vpop(DwVfpRegister dst, Condition cond = al) {
1029     vldm(ia_w, sp, dst, dst, cond);
1030   }
1031 
1032   // Jump unconditionally to given label.
jmp(Label* L)1033   void jmp(Label* L) { b(L, al); }
1034 
1035   // Check the code size generated from label to here.
SizeOfCodeGeneratedSince(Label* label)1036   int SizeOfCodeGeneratedSince(Label* label) {
1037     return pc_offset() - label->pos();
1038   }
1039 
1040   // Check the number of instructions generated from label to here.
InstructionsGeneratedSince(Label* label)1041   int InstructionsGeneratedSince(Label* label) {
1042     return SizeOfCodeGeneratedSince(label) / kInstrSize;
1043   }
1044 
1045   // Check whether an immediate fits an addressing mode 1 instruction.
1046   static bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1047 
1048   // Check whether an immediate fits an addressing mode 2 instruction.
1049   bool ImmediateFitsAddrMode2Instruction(int32_t imm32);
1050 
1051   // Class for scoping postponing the constant pool generation.
1052   class V8_NODISCARD BlockConstPoolScope {
1053    public:
BlockConstPoolScope(Assembler* assem)1054     explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1055       assem_->StartBlockConstPool();
1056     }
~BlockConstPoolScope()1057     ~BlockConstPoolScope() { assem_->EndBlockConstPool(); }
1058 
1059    private:
1060     Assembler* const assem_;
1061 
1062     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1063   };
1064 
1065   // Unused on this architecture.
MaybeEmitOutOfLineConstantPool()1066   void MaybeEmitOutOfLineConstantPool() {}
1067 
1068   // Record a deoptimization reason that can be used by a log or cpu profiler.
1069   // Use --trace-deopt to enable.
1070   void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
1071                          SourcePosition position, int id);
1072 
1073   // Record the emission of a constant pool.
1074   //
1075   // The emission of constant pool depends on the size of the code generated and
1076   // the number of RelocInfo recorded.
1077   // The Debug mechanism needs to map code offsets between two versions of a
1078   // function, compiled with and without debugger support (see for example
1079   // Debug::PrepareForBreakPoints()).
1080   // Compiling functions with debugger support generates additional code
1081   // (DebugCodegen::GenerateSlot()). This may affect the emission of the
1082   // constant pools and cause the version of the code with debugger support to
1083   // have constant pools generated in different places.
1084   // Recording the position and size of emitted constant pools allows to
1085   // correctly compute the offset mappings between the different versions of a
1086   // function in all situations.
1087   //
1088   // The parameter indicates the size of the constant pool (in bytes), including
1089   // the marker and branch over the data.
1090   void RecordConstPool(int size);
1091 
1092   // Writes a single byte or word of data in the code stream.  Used
1093   // for inline tables, e.g., jump-tables. CheckConstantPool() should be
1094   // called before any use of db/dd/dq/dp to ensure that constant pools
1095   // are not emitted as part of the tables generated.
1096   void db(uint8_t data);
1097   void dd(uint32_t data, RelocInfo::Mode rmode = RelocInfo::NO_INFO);
1098   void dq(uint64_t data, RelocInfo::Mode rmode = RelocInfo::NO_INFO);
dp(uintptr_t data, RelocInfo::Mode rmode = RelocInfo::NO_INFO)1099   void dp(uintptr_t data, RelocInfo::Mode rmode = RelocInfo::NO_INFO) {
1100     dd(data, rmode);
1101   }
1102 
1103   // Read/patch instructions
instr_at(int pos)1104   Instr instr_at(int pos) {
1105     return *reinterpret_cast<Instr*>(buffer_start_ + pos);
1106   }
instr_at_put(int pos, Instr instr)1107   void instr_at_put(int pos, Instr instr) {
1108     *reinterpret_cast<Instr*>(buffer_start_ + pos) = instr;
1109   }
instr_at(Address pc)1110   static Instr instr_at(Address pc) { return *reinterpret_cast<Instr*>(pc); }
instr_at_put(Address pc, Instr instr)1111   static void instr_at_put(Address pc, Instr instr) {
1112     *reinterpret_cast<Instr*>(pc) = instr;
1113   }
1114   static Condition GetCondition(Instr instr);
1115   static bool IsLdrRegisterImmediate(Instr instr);
1116   static bool IsVldrDRegisterImmediate(Instr instr);
1117   static int GetLdrRegisterImmediateOffset(Instr instr);
1118   static int GetVldrDRegisterImmediateOffset(Instr instr);
1119   static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
1120   static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
1121   static bool IsStrRegisterImmediate(Instr instr);
1122   static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1123   static bool IsAddRegisterImmediate(Instr instr);
1124   static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
1125   static Register GetRd(Instr instr);
1126   static Register GetRn(Instr instr);
1127   static Register GetRm(Instr instr);
1128   static bool IsPush(Instr instr);
1129   static bool IsPop(Instr instr);
1130   static bool IsStrRegFpOffset(Instr instr);
1131   static bool IsLdrRegFpOffset(Instr instr);
1132   static bool IsStrRegFpNegOffset(Instr instr);
1133   static bool IsLdrRegFpNegOffset(Instr instr);
1134   static bool IsLdrPcImmediateOffset(Instr instr);
1135   static bool IsBOrBlPcImmediateOffset(Instr instr);
1136   static bool IsVldrDPcImmediateOffset(Instr instr);
1137   static bool IsBlxReg(Instr instr);
1138   static bool IsBlxIp(Instr instr);
1139   static bool IsTstImmediate(Instr instr);
1140   static bool IsCmpRegister(Instr instr);
1141   static bool IsCmpImmediate(Instr instr);
1142   static Register GetCmpImmediateRegister(Instr instr);
1143   static int GetCmpImmediateRawImmediate(Instr instr);
1144   static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1145   static bool IsMovImmed(Instr instr);
1146   static bool IsOrrImmed(Instr instr);
1147   static bool IsMovT(Instr instr);
1148   static Instr GetMovTPattern();
1149   static bool IsMovW(Instr instr);
1150   static Instr GetMovWPattern();
1151   static Instr EncodeMovwImmediate(uint32_t immediate);
1152   static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate);
1153   static int DecodeShiftImm(Instr instr);
1154   static Instr PatchShiftImm(Instr instr, int immed);
1155 
1156   // Constants are accessed via pc relative addressing, which can reach −4095 to
1157   // 4095 for integer PC-relative loads, and −1020 to 1020 for floating-point
1158   // PC-relative loads, thereby defining a maximum distance between the
1159   // instruction and the accessed constant. Additionally, PC-relative loads
1160   // start at a delta from the actual load instruction's PC, so we can add this
1161   // on to the (positive) distance.
1162   static constexpr int kMaxDistToPcRelativeConstant =
1163       4095 + Instruction::kPcLoadDelta;
1164   // The constant pool needs to be jumped over, and has a marker, so the actual
1165   // distance from the instruction and start of the constant pool has to include
1166   // space for these two instructions.
1167   static constexpr int kMaxDistToIntPool =
1168       kMaxDistToPcRelativeConstant - 2 * kInstrSize;
1169   // Experimentally derived as sufficient for ~95% of compiles.
1170   static constexpr int kTypicalNumPending32Constants = 32;
1171   // The maximum number of pending constants is reached by a sequence of only
1172   // constant loads, which limits it to the number of constant loads that can
1173   // fit between the first constant load and the distance to the constant pool.
1174   static constexpr int kMaxNumPending32Constants =
1175       kMaxDistToIntPool / kInstrSize;
1176 
1177   // Postpone the generation of the constant pool for the specified number of
1178   // instructions.
1179   void BlockConstPoolFor(int instructions);
1180 
1181   // Check if is time to emit a constant pool.
1182   void CheckConstPool(bool force_emit, bool require_jump);
1183 
MaybeCheckConstPool()1184   V8_INLINE void MaybeCheckConstPool() {
1185     if (V8_UNLIKELY(pc_offset() >= constant_pool_deadline_)) {
1186       CheckConstPool(false, true);
1187     }
1188   }
1189 
1190   // Move a 32-bit immediate into a register, potentially via the constant pool.
1191   void Move32BitImmediate(Register rd, const Operand& x, Condition cond = al);
1192 
1193   // Get the code target object for a pc-relative call or jump.
1194   V8_INLINE Handle<Code> relative_code_target_object_handle_at(
1195       Address pc_) const;
1196 
1197  protected:
buffer_space() const1198   int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1199 
1200   // Decode branch instruction at pos and return branch target pos
1201   int target_at(int pos);
1202 
1203   // Patch branch instruction at pos to branch to given branch target pos
1204   void target_at_put(int pos, int target_pos);
1205 
1206   // Prevent contant pool emission until EndBlockConstPool is called.
1207   // Calls to this function can be nested but must be followed by an equal
1208   // number of call to EndBlockConstpool.
StartBlockConstPool()1209   void StartBlockConstPool() {
1210     if (const_pool_blocked_nesting_++ == 0) {
1211       // Prevent constant pool checks happening by resetting the deadline.
1212       constant_pool_deadline_ = kMaxInt;
1213     }
1214   }
1215 
1216   // Resume constant pool emission. Needs to be called as many times as
1217   // StartBlockConstPool to have an effect.
EndBlockConstPool()1218   void EndBlockConstPool() {
1219     if (--const_pool_blocked_nesting_ == 0) {
1220       if (first_const_pool_32_use_ >= 0) {
1221 #ifdef DEBUG
1222         // Check the constant pool hasn't been blocked for too long.
1223         DCHECK_LE(pc_offset(), first_const_pool_32_use_ + kMaxDistToIntPool);
1224 #endif
1225         // Reset the constant pool check back to the deadline.
1226         constant_pool_deadline_ = first_const_pool_32_use_ + kCheckPoolDeadline;
1227       }
1228     }
1229   }
1230 
is_const_pool_blocked() const1231   bool is_const_pool_blocked() const {
1232     return (const_pool_blocked_nesting_ > 0) ||
1233            (pc_offset() < no_const_pool_before_);
1234   }
1235 
has_pending_constants() const1236   bool has_pending_constants() const {
1237     bool result = !pending_32_bit_constants_.empty();
1238     DCHECK_EQ(result, first_const_pool_32_use_ != -1);
1239     return result;
1240   }
1241 
VfpRegisterIsAvailable(DwVfpRegister reg)1242   bool VfpRegisterIsAvailable(DwVfpRegister reg) {
1243     DCHECK(reg.is_valid());
1244     return IsEnabled(VFP32DREGS) ||
1245            (reg.code() < LowDwVfpRegister::kNumRegisters);
1246   }
1247 
VfpRegisterIsAvailable(QwNeonRegister reg)1248   bool VfpRegisterIsAvailable(QwNeonRegister reg) {
1249     DCHECK(reg.is_valid());
1250     return IsEnabled(VFP32DREGS) ||
1251            (reg.code() < LowDwVfpRegister::kNumRegisters / 2);
1252   }
1253 
1254   inline void emit(Instr x);
1255 
1256   // Code generation
1257   // The relocation writer's position is at least kGap bytes below the end of
1258   // the generated instructions. This is so that multi-instruction sequences do
1259   // not have to check for overflow. The same is true for writes of large
1260   // relocation info entries.
1261   static constexpr int kGap = 32;
1262   STATIC_ASSERT(AssemblerBase::kMinimalBufferSize >= 2 * kGap);
1263 
1264   // Relocation info generation
1265   // Each relocation is encoded as a variable size value
1266   static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1267   RelocInfoWriter reloc_info_writer;
1268 
1269   // ConstantPoolEntry records are used during code generation as temporary
1270   // containers for constants and code target addresses until they are emitted
1271   // to the constant pool. These records are temporarily stored in a separate
1272   // buffer until a constant pool is emitted.
1273   // If every instruction in a long sequence is accessing the pool, we need one
1274   // pending relocation entry per instruction.
1275 
1276   // The buffers of pending constant pool entries.
1277   base::SmallVector<ConstantPoolEntry, kTypicalNumPending32Constants>
1278       pending_32_bit_constants_;
1279 
1280   // Scratch registers available for use by the Assembler.
1281   RegList scratch_register_list_;
1282   VfpRegList scratch_vfp_register_list_;
1283 
1284  private:
1285   // Avoid overflows for displacements etc.
1286   static const int kMaximalBufferSize = 512 * MB;
1287 
1288   // Constant pool generation
1289   // Pools are emitted in the instruction stream, preferably after unconditional
1290   // jumps or after returns from functions (in dead code locations).
1291   // If a long code sequence does not contain unconditional jumps, it is
1292   // necessary to emit the constant pool before the pool gets too far from the
1293   // location it is accessed from. In this case, we emit a jump over the emitted
1294   // constant pool.
1295   // Constants in the pool may be addresses of functions that gets relocated;
1296   // if so, a relocation info entry is associated to the constant pool entry.
1297 
1298   // Repeated checking whether the constant pool should be emitted is rather
1299   // expensive. Instead, we check once a deadline is hit; the deadline being
1300   // when there is a possibility that MaybeCheckConstPool won't be called before
1301   // kMaxDistToIntPoolWithHeader is exceeded. Since MaybeCheckConstPool is
1302   // called in CheckBuffer, this means that kGap is an upper bound on this
1303   // check. Use 2 * kGap just to give it some slack around BlockConstPoolScopes.
1304   static constexpr int kCheckPoolDeadline = kMaxDistToIntPool - 2 * kGap;
1305 
1306   // pc offset of the upcoming constant pool deadline. Equivalent to
1307   // first_const_pool_32_use_ + kCheckPoolDeadline.
1308   int constant_pool_deadline_;
1309 
1310   // Emission of the constant pool may be blocked in some code sequences.
1311   int const_pool_blocked_nesting_;  // Block emission if this is not zero.
1312   int no_const_pool_before_;        // Block emission before this pc offset.
1313 
1314   // Keep track of the first instruction requiring a constant pool entry
1315   // since the previous constant pool was emitted.
1316   int first_const_pool_32_use_;
1317 
1318   // The bound position, before this we cannot do instruction elimination.
1319   int last_bound_pos_;
1320 
1321   V8_INLINE void CheckBuffer();
1322   void GrowBuffer();
1323 
1324   // Instruction generation
1325   void AddrMode1(Instr instr, Register rd, Register rn, const Operand& x);
1326   // Attempt to encode operand |x| for instruction |instr| and return true on
1327   // success. The result will be encoded in |instr| directly. This method may
1328   // change the opcode if deemed beneficial, for instance, MOV may be turned
1329   // into MVN, ADD into SUB, AND into BIC, ...etc.  The only reason this method
1330   // may fail is that the operand is an immediate that cannot be encoded.
1331   bool AddrMode1TryEncodeOperand(Instr* instr, const Operand& x);
1332 
1333   void AddrMode2(Instr instr, Register rd, const MemOperand& x);
1334   void AddrMode3(Instr instr, Register rd, const MemOperand& x);
1335   void AddrMode4(Instr instr, Register rn, RegList rl);
1336   void AddrMode5(Instr instr, CRegister crd, const MemOperand& x);
1337 
1338   // Labels
1339   void print(const Label* L);
1340   void bind_to(Label* L, int pos);
1341   void next(Label* L);
1342 
1343   // Record reloc info for current pc_
1344   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1345   void ConstantPoolAddEntry(int position, RelocInfo::Mode rmode,
1346                             intptr_t value);
1347   void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
1348 
1349   int WriteCodeComments();
1350 
1351   friend class RelocInfo;
1352   friend class BlockConstPoolScope;
1353   friend class EnsureSpace;
1354   friend class UseScratchRegisterScope;
1355 };
1356 
1357 class EnsureSpace {
1358  public:
1359   V8_INLINE explicit EnsureSpace(Assembler* assembler);
1360 };
1361 
1362 class PatchingAssembler : public Assembler {
1363  public:
1364   PatchingAssembler(const AssemblerOptions& options, byte* address,
1365                     int instructions);
1366   ~PatchingAssembler();
1367 
1368   void Emit(Address addr);
1369   void PadWithNops();
1370 };
1371 
1372 // This scope utility allows scratch registers to be managed safely. The
1373 // Assembler's GetScratchRegisterList() is used as a pool of scratch
1374 // registers. These registers can be allocated on demand, and will be returned
1375 // at the end of the scope.
1376 //
1377 // When the scope ends, the Assembler's list will be restored to its original
1378 // state, even if the list is modified by some other means. Note that this scope
1379 // can be nested but the destructors need to run in the opposite order as the
1380 // constructors. We do not have assertions for this.
1381 class V8_EXPORT_PRIVATE V8_NODISCARD UseScratchRegisterScope {
1382  public:
1383   explicit UseScratchRegisterScope(Assembler* assembler);
1384   ~UseScratchRegisterScope();
1385 
1386   // Take a register from the list and return it.
1387   Register Acquire();
AcquireS()1388   SwVfpRegister AcquireS() { return AcquireVfp<SwVfpRegister>(); }
AcquireLowD()1389   LowDwVfpRegister AcquireLowD() { return AcquireVfp<LowDwVfpRegister>(); }
AcquireD()1390   DwVfpRegister AcquireD() {
1391     DwVfpRegister reg = AcquireVfp<DwVfpRegister>();
1392     DCHECK(assembler_->VfpRegisterIsAvailable(reg));
1393     return reg;
1394   }
AcquireQ()1395   QwNeonRegister AcquireQ() {
1396     QwNeonRegister reg = AcquireVfp<QwNeonRegister>();
1397     DCHECK(assembler_->VfpRegisterIsAvailable(reg));
1398     return reg;
1399   }
1400 
1401   // Check if we have registers available to acquire.
CanAcquire() const1402   bool CanAcquire() const {
1403     return !assembler_->GetScratchRegisterList()->is_empty();
1404   }
CanAcquireD() const1405   bool CanAcquireD() const { return CanAcquireVfp<DwVfpRegister>(); }
1406 
Include(const Register& reg1, const Register& reg2 = no_reg)1407   void Include(const Register& reg1, const Register& reg2 = no_reg) {
1408     RegList* available = assembler_->GetScratchRegisterList();
1409     DCHECK_NOT_NULL(available);
1410     DCHECK(!available->has(reg1));
1411     DCHECK(!available->has(reg2));
1412     available->set(reg1);
1413     available->set(reg2);
1414   }
Exclude(const Register& reg1, const Register& reg2 = no_reg)1415   void Exclude(const Register& reg1, const Register& reg2 = no_reg) {
1416     RegList* available = assembler_->GetScratchRegisterList();
1417     DCHECK_NOT_NULL(available);
1418     DCHECK(available->has(reg1));
1419     DCHECK_IMPLIES(reg2.is_valid(), available->has(reg2));
1420     available->clear(RegList{reg1, reg2});
1421   }
1422 
1423  private:
1424   friend class Assembler;
1425   friend class TurboAssembler;
1426 
1427   template <typename T>
1428   bool CanAcquireVfp() const;
1429 
1430   template <typename T>
1431   T AcquireVfp();
1432 
1433   Assembler* assembler_;
1434   // Available scratch registers at the start of this scope.
1435   RegList old_available_;
1436   VfpRegList old_available_vfp_;
1437 };
1438 
1439 // Helper struct for load lane and store lane to indicate which opcode to use
1440 // and what memory size to be encoded in the opcode, and the new lane index.
1441 class LoadStoreLaneParams {
1442  public:
1443   bool low_op;
1444   NeonSize sz;
1445   uint8_t laneidx;
1446   // The register mapping on ARM (1 Q to 2 D), means that loading/storing high
1447   // lanes of a Q register is equivalent to loading/storing the high D reg,
1448   // modulo number of lanes in a D reg. This constructor decides, based on the
1449   // laneidx and load/store size, whether the low or high D reg is accessed, and
1450   // what the new lane index is.
1451   LoadStoreLaneParams(MachineRepresentation rep, uint8_t laneidx);
1452 
1453  private:
LoadStoreLaneParams(uint8_t laneidx, NeonSize sz, int lanes)1454   LoadStoreLaneParams(uint8_t laneidx, NeonSize sz, int lanes)
1455       : low_op(laneidx < lanes), sz(sz), laneidx(laneidx % lanes) {}
1456 };
1457 
1458 }  // namespace internal
1459 }  // namespace v8
1460 
1461 #endif  // V8_CODEGEN_ARM_ASSEMBLER_ARM_H_
1462