assembler-arm.h revision 13e2dadd00298019ed862f2b2fc5068bba730bcf
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_ARM_ASSEMBLER_ARM_H_
41#define V8_ARM_ASSEMBLER_ARM_H_
42
43#include <stdio.h>
44#include <vector>
45
46#include "src/arm/constants-arm.h"
47#include "src/assembler.h"
48
49namespace v8 {
50namespace internal {
51
52// clang-format off
53#define GENERAL_REGISTERS(V)                              \
54  V(r0)  V(r1)  V(r2)  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)  \
55  V(r8)  V(r9)  V(r10) V(fp)  V(ip)  V(sp)  V(lr)  V(pc)
56
57#define ALLOCATABLE_GENERAL_REGISTERS(V) \
58  V(r0)  V(r1)  V(r2)  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)  V(r8)
59
60#define FLOAT_REGISTERS(V)                                \
61  V(s0)  V(s1)  V(s2)  V(s3)  V(s4)  V(s5)  V(s6)  V(s7)  \
62  V(s8)  V(s9)  V(s10) V(s11) V(s12) V(s13) V(s14) V(s15) \
63  V(s16) V(s17) V(s18) V(s19) V(s20) V(s21) V(s22) V(s23) \
64  V(s24) V(s25) V(s26) V(s27) V(s28) V(s29) V(s30) V(s31)
65
66#define DOUBLE_REGISTERS(V)                               \
67  V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
68  V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \
69  V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
70  V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
71
72#define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
73  V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
74  V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13)               \
75  V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
76  V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
77
78#define ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(V)          \
79  V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
80  V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13)               \
81// clang-format on
82
83// CPU Registers.
84//
85// 1) We would prefer to use an enum, but enum values are assignment-
86// compatible with int, which has caused code-generation bugs.
87//
88// 2) We would prefer to use a class instead of a struct but we don't like
89// the register initialization to depend on the particular initialization
90// order (which appears to be different on OS X, Linux, and Windows for the
91// installed versions of C++ we tried). Using a struct permits C-style
92// "initialization". Also, the Register objects cannot be const as this
93// forces initialization stubs in MSVC, making us dependent on initialization
94// order.
95//
96// 3) By not using an enum, we are possibly preventing the compiler from
97// doing certain constant folds, which may significantly reduce the
98// code generated for some assembly instructions (because they boil down
99// to a few constants). If this is a problem, we could change the code
100// such that we use an enum in optimized mode, and the struct in debug
101// mode. This way we get the compile-time error checking in debug mode
102// and best performance in optimized code.
103
104struct Register {
105  enum Code {
106#define REGISTER_CODE(R) kCode_##R,
107    GENERAL_REGISTERS(REGISTER_CODE)
108#undef REGISTER_CODE
109        kAfterLast,
110    kCode_no_reg = -1
111  };
112
113  static const int kNumRegisters = Code::kAfterLast;
114
115  static Register from_code(int code) {
116    DCHECK(code >= 0);
117    DCHECK(code < kNumRegisters);
118    Register r = {code};
119    return r;
120  }
121  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
122  bool is(Register reg) const { return reg_code == reg.reg_code; }
123  int code() const {
124    DCHECK(is_valid());
125    return reg_code;
126  }
127  int bit() const {
128    DCHECK(is_valid());
129    return 1 << reg_code;
130  }
131  void set_code(int code) {
132    reg_code = code;
133    DCHECK(is_valid());
134  }
135
136  // Unfortunately we can't make this private in a struct.
137  int reg_code;
138};
139
140// r7: context register
141// r8: constant pool pointer register if FLAG_enable_embedded_constant_pool.
142// r9: lithium scratch
143#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
144GENERAL_REGISTERS(DECLARE_REGISTER)
145#undef DECLARE_REGISTER
146const Register no_reg = {Register::kCode_no_reg};
147
148static const bool kSimpleFPAliasing = false;
149
150// Single word VFP register.
151struct SwVfpRegister {
152  enum Code {
153#define REGISTER_CODE(R) kCode_##R,
154    FLOAT_REGISTERS(REGISTER_CODE)
155#undef REGISTER_CODE
156        kAfterLast,
157    kCode_no_reg = -1
158  };
159
160  static const int kMaxNumRegisters = Code::kAfterLast;
161
162  static const int kSizeInBytes = 4;
163
164  bool is_valid() const { return 0 <= reg_code && reg_code < 32; }
165  bool is(SwVfpRegister reg) const { return reg_code == reg.reg_code; }
166  int code() const {
167    DCHECK(is_valid());
168    return reg_code;
169  }
170  int bit() const {
171    DCHECK(is_valid());
172    return 1 << reg_code;
173  }
174  static SwVfpRegister from_code(int code) {
175    SwVfpRegister r = {code};
176    return r;
177  }
178  void split_code(int* vm, int* m) const {
179    DCHECK(is_valid());
180    *m = reg_code & 0x1;
181    *vm = reg_code >> 1;
182  }
183
184  int reg_code;
185};
186
187typedef SwVfpRegister FloatRegister;
188
189// Double word VFP register.
190struct DwVfpRegister {
191  enum Code {
192#define REGISTER_CODE(R) kCode_##R,
193    DOUBLE_REGISTERS(REGISTER_CODE)
194#undef REGISTER_CODE
195        kAfterLast,
196    kCode_no_reg = -1
197  };
198
199  static const int kMaxNumRegisters = Code::kAfterLast;
200
201  inline static int NumRegisters();
202
203  // A few double registers are reserved: one as a scratch register and one to
204  // hold 0.0, that does not fit in the immediate field of vmov instructions.
205  //  d14: 0.0
206  //  d15: scratch register.
207  static const int kSizeInBytes = 8;
208
209  bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
210  bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
211  int code() const {
212    DCHECK(is_valid());
213    return reg_code;
214  }
215  int bit() const {
216    DCHECK(is_valid());
217    return 1 << reg_code;
218  }
219
220  static DwVfpRegister from_code(int code) {
221    DwVfpRegister r = {code};
222    return r;
223  }
224  void split_code(int* vm, int* m) const {
225    DCHECK(is_valid());
226    *m = (reg_code & 0x10) >> 4;
227    *vm = reg_code & 0x0F;
228  }
229
230  int reg_code;
231};
232
233
234typedef DwVfpRegister DoubleRegister;
235
236
237// Double word VFP register d0-15.
238struct LowDwVfpRegister {
239 public:
240  static const int kMaxNumLowRegisters = 16;
241  operator DwVfpRegister() const {
242    DwVfpRegister r = { reg_code };
243    return r;
244  }
245  static LowDwVfpRegister from_code(int code) {
246    LowDwVfpRegister r = { code };
247    return r;
248  }
249
250  bool is_valid() const {
251    return 0 <= reg_code && reg_code < kMaxNumLowRegisters;
252  }
253  bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
254  bool is(LowDwVfpRegister reg) const { return reg_code == reg.reg_code; }
255  int code() const {
256    DCHECK(is_valid());
257    return reg_code;
258  }
259  SwVfpRegister low() const {
260    SwVfpRegister reg;
261    reg.reg_code = reg_code * 2;
262
263    DCHECK(reg.is_valid());
264    return reg;
265  }
266  SwVfpRegister high() const {
267    SwVfpRegister reg;
268    reg.reg_code = (reg_code * 2) + 1;
269
270    DCHECK(reg.is_valid());
271    return reg;
272  }
273
274  int reg_code;
275};
276
277
278// Quad word NEON register.
279struct QwNeonRegister {
280  static const int kMaxNumRegisters = 16;
281
282  static QwNeonRegister from_code(int code) {
283    QwNeonRegister r = { code };
284    return r;
285  }
286
287  bool is_valid() const {
288    return (0 <= reg_code) && (reg_code < kMaxNumRegisters);
289  }
290  bool is(QwNeonRegister reg) const { return reg_code == reg.reg_code; }
291  int code() const {
292    DCHECK(is_valid());
293    return reg_code;
294  }
295  void split_code(int* vm, int* m) const {
296    DCHECK(is_valid());
297    int encoded_code = reg_code << 1;
298    *m = (encoded_code & 0x10) >> 4;
299    *vm = encoded_code & 0x0F;
300  }
301
302  int reg_code;
303};
304
305
306typedef QwNeonRegister QuadRegister;
307
308typedef QwNeonRegister Simd128Register;
309
310// Support for the VFP registers s0 to s31 (d0 to d15).
311// Note that "s(N):s(N+1)" is the same as "d(N/2)".
312const SwVfpRegister s0  = {  0 };
313const SwVfpRegister s1  = {  1 };
314const SwVfpRegister s2  = {  2 };
315const SwVfpRegister s3  = {  3 };
316const SwVfpRegister s4  = {  4 };
317const SwVfpRegister s5  = {  5 };
318const SwVfpRegister s6  = {  6 };
319const SwVfpRegister s7  = {  7 };
320const SwVfpRegister s8  = {  8 };
321const SwVfpRegister s9  = {  9 };
322const SwVfpRegister s10 = { 10 };
323const SwVfpRegister s11 = { 11 };
324const SwVfpRegister s12 = { 12 };
325const SwVfpRegister s13 = { 13 };
326const SwVfpRegister s14 = { 14 };
327const SwVfpRegister s15 = { 15 };
328const SwVfpRegister s16 = { 16 };
329const SwVfpRegister s17 = { 17 };
330const SwVfpRegister s18 = { 18 };
331const SwVfpRegister s19 = { 19 };
332const SwVfpRegister s20 = { 20 };
333const SwVfpRegister s21 = { 21 };
334const SwVfpRegister s22 = { 22 };
335const SwVfpRegister s23 = { 23 };
336const SwVfpRegister s24 = { 24 };
337const SwVfpRegister s25 = { 25 };
338const SwVfpRegister s26 = { 26 };
339const SwVfpRegister s27 = { 27 };
340const SwVfpRegister s28 = { 28 };
341const SwVfpRegister s29 = { 29 };
342const SwVfpRegister s30 = { 30 };
343const SwVfpRegister s31 = { 31 };
344
345const DwVfpRegister no_dreg = { -1 };
346const LowDwVfpRegister d0 = { 0 };
347const LowDwVfpRegister d1 = { 1 };
348const LowDwVfpRegister d2 = { 2 };
349const LowDwVfpRegister d3 = { 3 };
350const LowDwVfpRegister d4 = { 4 };
351const LowDwVfpRegister d5 = { 5 };
352const LowDwVfpRegister d6 = { 6 };
353const LowDwVfpRegister d7 = { 7 };
354const LowDwVfpRegister d8 = { 8 };
355const LowDwVfpRegister d9 = { 9 };
356const LowDwVfpRegister d10 = { 10 };
357const LowDwVfpRegister d11 = { 11 };
358const LowDwVfpRegister d12 = { 12 };
359const LowDwVfpRegister d13 = { 13 };
360const LowDwVfpRegister d14 = { 14 };
361const LowDwVfpRegister d15 = { 15 };
362const DwVfpRegister d16 = { 16 };
363const DwVfpRegister d17 = { 17 };
364const DwVfpRegister d18 = { 18 };
365const DwVfpRegister d19 = { 19 };
366const DwVfpRegister d20 = { 20 };
367const DwVfpRegister d21 = { 21 };
368const DwVfpRegister d22 = { 22 };
369const DwVfpRegister d23 = { 23 };
370const DwVfpRegister d24 = { 24 };
371const DwVfpRegister d25 = { 25 };
372const DwVfpRegister d26 = { 26 };
373const DwVfpRegister d27 = { 27 };
374const DwVfpRegister d28 = { 28 };
375const DwVfpRegister d29 = { 29 };
376const DwVfpRegister d30 = { 30 };
377const DwVfpRegister d31 = { 31 };
378
379const QwNeonRegister q0  = {  0 };
380const QwNeonRegister q1  = {  1 };
381const QwNeonRegister q2  = {  2 };
382const QwNeonRegister q3  = {  3 };
383const QwNeonRegister q4  = {  4 };
384const QwNeonRegister q5  = {  5 };
385const QwNeonRegister q6  = {  6 };
386const QwNeonRegister q7  = {  7 };
387const QwNeonRegister q8  = {  8 };
388const QwNeonRegister q9  = {  9 };
389const QwNeonRegister q10 = { 10 };
390const QwNeonRegister q11 = { 11 };
391const QwNeonRegister q12 = { 12 };
392const QwNeonRegister q13 = { 13 };
393const QwNeonRegister q14 = { 14 };
394const QwNeonRegister q15 = { 15 };
395
396
397// Aliases for double registers.  Defined using #define instead of
398// "static const DwVfpRegister&" because Clang complains otherwise when a
399// compilation unit that includes this header doesn't use the variables.
400#define kFirstCalleeSavedDoubleReg d8
401#define kLastCalleeSavedDoubleReg d15
402#define kDoubleRegZero d14
403#define kScratchDoubleReg d15
404
405
406// Coprocessor register
407struct CRegister {
408  bool is_valid() const { return 0 <= reg_code && reg_code < 16; }
409  bool is(CRegister creg) const { return reg_code == creg.reg_code; }
410  int code() const {
411    DCHECK(is_valid());
412    return reg_code;
413  }
414  int bit() const {
415    DCHECK(is_valid());
416    return 1 << reg_code;
417  }
418
419  // Unfortunately we can't make this private in a struct.
420  int reg_code;
421};
422
423
424const CRegister no_creg = { -1 };
425
426const CRegister cr0  = {  0 };
427const CRegister cr1  = {  1 };
428const CRegister cr2  = {  2 };
429const CRegister cr3  = {  3 };
430const CRegister cr4  = {  4 };
431const CRegister cr5  = {  5 };
432const CRegister cr6  = {  6 };
433const CRegister cr7  = {  7 };
434const CRegister cr8  = {  8 };
435const CRegister cr9  = {  9 };
436const CRegister cr10 = { 10 };
437const CRegister cr11 = { 11 };
438const CRegister cr12 = { 12 };
439const CRegister cr13 = { 13 };
440const CRegister cr14 = { 14 };
441const CRegister cr15 = { 15 };
442
443
444// Coprocessor number
445enum Coprocessor {
446  p0  = 0,
447  p1  = 1,
448  p2  = 2,
449  p3  = 3,
450  p4  = 4,
451  p5  = 5,
452  p6  = 6,
453  p7  = 7,
454  p8  = 8,
455  p9  = 9,
456  p10 = 10,
457  p11 = 11,
458  p12 = 12,
459  p13 = 13,
460  p14 = 14,
461  p15 = 15
462};
463
464
465// -----------------------------------------------------------------------------
466// Machine instruction Operands
467
468// Class Operand represents a shifter operand in data processing instructions
469class Operand BASE_EMBEDDED {
470 public:
471  // immediate
472  INLINE(explicit Operand(int32_t immediate,
473         RelocInfo::Mode rmode = RelocInfo::NONE32));
474  INLINE(static Operand Zero()) {
475    return Operand(static_cast<int32_t>(0));
476  }
477  INLINE(explicit Operand(const ExternalReference& f));
478  explicit Operand(Handle<Object> handle);
479  INLINE(explicit Operand(Smi* value));
480
481  // rm
482  INLINE(explicit Operand(Register rm));
483
484  // rm <shift_op> shift_imm
485  explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
486  INLINE(static Operand SmiUntag(Register rm)) {
487    return Operand(rm, ASR, kSmiTagSize);
488  }
489  INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
490    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
491    return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
492  }
493  INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) {
494    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
495    return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
496  }
497
498  // rm <shift_op> rs
499  explicit Operand(Register rm, ShiftOp shift_op, Register rs);
500
501  // Return true if this is a register operand.
502  INLINE(bool is_reg() const);
503
504  // Return the number of actual instructions required to implement the given
505  // instruction for this particular operand. This can be a single instruction,
506  // if no load into the ip register is necessary, or anything between 2 and 4
507  // instructions when we need to load from the constant pool (depending upon
508  // whether the constant pool entry is in the small or extended section). If
509  // the instruction this operand is used for is a MOV or MVN instruction the
510  // actual instruction to use is required for this calculation. For other
511  // instructions instr is ignored.
512  //
513  // The value returned is only valid as long as no entries are added to the
514  // constant pool between this call and the actual instruction being emitted.
515  int instructions_required(const Assembler* assembler, Instr instr = 0) const;
516  bool must_output_reloc_info(const Assembler* assembler) const;
517
518  inline int32_t immediate() const {
519    DCHECK(!rm_.is_valid());
520    return imm32_;
521  }
522
523  Register rm() const { return rm_; }
524  Register rs() const { return rs_; }
525  ShiftOp shift_op() const { return shift_op_; }
526
527 private:
528  Register rm_;
529  Register rs_;
530  ShiftOp shift_op_;
531  int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
532  int32_t imm32_;  // valid if rm_ == no_reg
533  RelocInfo::Mode rmode_;
534
535  friend class Assembler;
536};
537
538
539// Class MemOperand represents a memory operand in load and store instructions
540class MemOperand BASE_EMBEDDED {
541 public:
542  // [rn +/- offset]      Offset/NegOffset
543  // [rn +/- offset]!     PreIndex/NegPreIndex
544  // [rn], +/- offset     PostIndex/NegPostIndex
545  // offset is any signed 32-bit value; offset is first loaded to register ip if
546  // it does not fit the addressing mode (12-bit unsigned and sign bit)
547  explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
548
549  // [rn +/- rm]          Offset/NegOffset
550  // [rn +/- rm]!         PreIndex/NegPreIndex
551  // [rn], +/- rm         PostIndex/NegPostIndex
552  explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
553
554  // [rn +/- rm <shift_op> shift_imm]      Offset/NegOffset
555  // [rn +/- rm <shift_op> shift_imm]!     PreIndex/NegPreIndex
556  // [rn], +/- rm <shift_op> shift_imm     PostIndex/NegPostIndex
557  explicit MemOperand(Register rn, Register rm,
558                      ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
559  INLINE(static MemOperand PointerAddressFromSmiKey(Register array,
560                                                    Register key,
561                                                    AddrMode am = Offset)) {
562    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
563    return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
564  }
565
566  void set_offset(int32_t offset) {
567      DCHECK(rm_.is(no_reg));
568      offset_ = offset;
569  }
570
571  uint32_t offset() const {
572      DCHECK(rm_.is(no_reg));
573      return offset_;
574  }
575
576  Register rn() const { return rn_; }
577  Register rm() const { return rm_; }
578  AddrMode am() const { return am_; }
579
580  bool OffsetIsUint12Encodable() const {
581    return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
582  }
583
584 private:
585  Register rn_;  // base
586  Register rm_;  // register offset
587  int32_t offset_;  // valid if rm_ == no_reg
588  ShiftOp shift_op_;
589  int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
590  AddrMode am_;  // bits P, U, and W
591
592  friend class Assembler;
593};
594
595
596// Class NeonMemOperand represents a memory operand in load and
597// store NEON instructions
598class NeonMemOperand BASE_EMBEDDED {
599 public:
600  // [rn {:align}]       Offset
601  // [rn {:align}]!      PostIndex
602  explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
603
604  // [rn {:align}], rm   PostIndex
605  explicit NeonMemOperand(Register rn, Register rm, int align = 0);
606
607  Register rn() const { return rn_; }
608  Register rm() const { return rm_; }
609  int align() const { return align_; }
610
611 private:
612  void SetAlignment(int align);
613
614  Register rn_;  // base
615  Register rm_;  // register increment
616  int align_;
617};
618
619
620// Class NeonListOperand represents a list of NEON registers
621class NeonListOperand BASE_EMBEDDED {
622 public:
623  explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
624  DoubleRegister base() const { return base_; }
625  NeonListType type() const { return type_; }
626 private:
627  DoubleRegister base_;
628  NeonListType type_;
629};
630
631
632struct VmovIndex {
633  unsigned char index;
634};
635const VmovIndex VmovIndexLo = { 0 };
636const VmovIndex VmovIndexHi = { 1 };
637
638class Assembler : public AssemblerBase {
639 public:
640  // Create an assembler. Instructions and relocation information are emitted
641  // into a buffer, with the instructions starting from the beginning and the
642  // relocation information starting from the end of the buffer. See CodeDesc
643  // for a detailed comment on the layout (globals.h).
644  //
645  // If the provided buffer is NULL, the assembler allocates and grows its own
646  // buffer, and buffer_size determines the initial buffer size. The buffer is
647  // owned by the assembler and deallocated upon destruction of the assembler.
648  //
649  // If the provided buffer is not NULL, the assembler uses the provided buffer
650  // for code generation and assumes its size to be buffer_size. If the buffer
651  // is too small, a fatal error occurs. No deallocation of the buffer is done
652  // upon destruction of the assembler.
653  Assembler(Isolate* isolate, void* buffer, int buffer_size);
654  virtual ~Assembler();
655
656  // GetCode emits any pending (non-emitted) code and fills the descriptor
657  // desc. GetCode() is idempotent; it returns the same result if no other
658  // Assembler functions are invoked in between GetCode() calls.
659  void GetCode(CodeDesc* desc);
660
661  // Label operations & relative jumps (PPUM Appendix D)
662  //
663  // Takes a branch opcode (cc) and a label (L) and generates
664  // either a backward branch or a forward branch and links it
665  // to the label fixup chain. Usage:
666  //
667  // Label L;    // unbound label
668  // j(cc, &L);  // forward branch to unbound label
669  // bind(&L);   // bind label to the current pc
670  // j(cc, &L);  // backward branch to bound label
671  // bind(&L);   // illegal: a label may be bound only once
672  //
673  // Note: The same Label can be used for forward and backward branches
674  // but it may be bound only once.
675
676  void bind(Label* L);  // binds an unbound label L to the current code position
677
678  // Returns the branch offset to the given label from the current code position
679  // Links the label to the current position if it is still unbound
680  // Manages the jump elimination optimization if the second parameter is true.
681  int branch_offset(Label* L);
682
683  // Returns true if the given pc address is the start of a constant pool load
684  // instruction sequence.
685  INLINE(static bool is_constant_pool_load(Address pc));
686
687  // Return the address in the constant pool of the code target address used by
688  // the branch/call instruction at pc, or the object in a mov.
689  INLINE(static Address constant_pool_entry_address(Address pc,
690                                                    Address constant_pool));
691
692  // Read/Modify the code target address in the branch/call instruction at pc.
693  INLINE(static Address target_address_at(Address pc, Address constant_pool));
694  INLINE(static void set_target_address_at(
695      Isolate* isolate, Address pc, Address constant_pool, Address target,
696      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
697  INLINE(static Address target_address_at(Address pc, Code* code)) {
698    Address constant_pool = code ? code->constant_pool() : NULL;
699    return target_address_at(pc, constant_pool);
700  }
701  INLINE(static void set_target_address_at(
702      Isolate* isolate, Address pc, Code* code, Address target,
703      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) {
704    Address constant_pool = code ? code->constant_pool() : NULL;
705    set_target_address_at(isolate, pc, constant_pool, target,
706                          icache_flush_mode);
707  }
708
709  // Return the code target address at a call site from the return address
710  // of that call in the instruction stream.
711  INLINE(static Address target_address_from_return_address(Address pc));
712
713  // Given the address of the beginning of a call, return the address
714  // in the instruction stream that the call will return from.
715  INLINE(static Address return_address_from_call_start(Address pc));
716
717  // This sets the branch destination (which is in the constant pool on ARM).
718  // This is for calls and branches within generated code.
719  inline static void deserialization_set_special_target_at(
720      Isolate* isolate, Address constant_pool_entry, Code* code,
721      Address target);
722
723  // This sets the internal reference at the pc.
724  inline static void deserialization_set_target_internal_reference_at(
725      Isolate* isolate, Address pc, Address target,
726      RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
727
728  // Here we are patching the address in the constant pool, not the actual call
729  // instruction.  The address in the constant pool is the same size as a
730  // pointer.
731  static const int kSpecialTargetSize = kPointerSize;
732
733  // Size of an instruction.
734  static const int kInstrSize = sizeof(Instr);
735
736  // Distance between start of patched debug break slot and the emitted address
737  // to jump to.
738  // Patched debug break slot code is:
739  //  ldr  ip, [pc, #0]   @ emited address and start
740  //  blx  ip
741  static const int kPatchDebugBreakSlotAddressOffset = 2 * kInstrSize;
742
743  // Difference between address of current opcode and value read from pc
744  // register.
745  static const int kPcLoadDelta = 8;
746
747  static const int kDebugBreakSlotInstructions = 4;
748  static const int kDebugBreakSlotLength =
749      kDebugBreakSlotInstructions * kInstrSize;
750
751  // ---------------------------------------------------------------------------
752  // Code generation
753
754  // Insert the smallest number of nop instructions
755  // possible to align the pc offset to a multiple
756  // of m. m must be a power of 2 (>= 4).
757  void Align(int m);
758  // Insert the smallest number of zero bytes possible to align the pc offset
759  // to a mulitple of m. m must be a power of 2 (>= 2).
760  void DataAlign(int m);
761  // Aligns code to something that's optimal for a jump target for the platform.
762  void CodeTargetAlign();
763
764  // Branch instructions
765  void b(int branch_offset, Condition cond = al);
766  void bl(int branch_offset, Condition cond = al);
767  void blx(int branch_offset);  // v5 and above
768  void blx(Register target, Condition cond = al);  // v5 and above
769  void bx(Register target, Condition cond = al);  // v5 and above, plus v4t
770
771  // Convenience branch instructions using labels
772  void b(Label* L, Condition cond = al);
773  void b(Condition cond, Label* L) { b(L, cond); }
774  void bl(Label* L, Condition cond = al);
775  void bl(Condition cond, Label* L) { bl(L, cond); }
776  void blx(Label* L);  // v5 and above
777
778  // Data-processing instructions
779
780  void and_(Register dst, Register src1, const Operand& src2,
781            SBit s = LeaveCC, Condition cond = al);
782
783  void eor(Register dst, Register src1, const Operand& src2,
784           SBit s = LeaveCC, Condition cond = al);
785
786  void sub(Register dst, Register src1, const Operand& src2,
787           SBit s = LeaveCC, Condition cond = al);
788  void sub(Register dst, Register src1, Register src2,
789           SBit s = LeaveCC, Condition cond = al) {
790    sub(dst, src1, Operand(src2), s, cond);
791  }
792
793  void rsb(Register dst, Register src1, const Operand& src2,
794           SBit s = LeaveCC, Condition cond = al);
795
796  void add(Register dst, Register src1, const Operand& src2,
797           SBit s = LeaveCC, Condition cond = al);
798  void add(Register dst, Register src1, Register src2,
799           SBit s = LeaveCC, Condition cond = al) {
800    add(dst, src1, Operand(src2), s, cond);
801  }
802
803  void adc(Register dst, Register src1, const Operand& src2,
804           SBit s = LeaveCC, Condition cond = al);
805
806  void sbc(Register dst, Register src1, const Operand& src2,
807           SBit s = LeaveCC, Condition cond = al);
808
809  void rsc(Register dst, Register src1, const Operand& src2,
810           SBit s = LeaveCC, Condition cond = al);
811
812  void tst(Register src1, const Operand& src2, Condition cond = al);
813  void tst(Register src1, Register src2, Condition cond = al) {
814    tst(src1, Operand(src2), cond);
815  }
816
817  void teq(Register src1, const Operand& src2, Condition cond = al);
818
819  void cmp(Register src1, const Operand& src2, Condition cond = al);
820  void cmp(Register src1, Register src2, Condition cond = al) {
821    cmp(src1, Operand(src2), cond);
822  }
823  void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
824
825  void cmn(Register src1, const Operand& src2, Condition cond = al);
826
827  void orr(Register dst, Register src1, const Operand& src2,
828           SBit s = LeaveCC, Condition cond = al);
829  void orr(Register dst, Register src1, Register src2,
830           SBit s = LeaveCC, Condition cond = al) {
831    orr(dst, src1, Operand(src2), s, cond);
832  }
833
834  void mov(Register dst, const Operand& src,
835           SBit s = LeaveCC, Condition cond = al);
836  void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
837    mov(dst, Operand(src), s, cond);
838  }
839
840  // Load the position of the label relative to the generated code object
841  // pointer in a register.
842  void mov_label_offset(Register dst, Label* label);
843
844  // ARMv7 instructions for loading a 32 bit immediate in two instructions.
845  // The constant for movw and movt should be in the range 0-0xffff.
846  void movw(Register reg, uint32_t immediate, Condition cond = al);
847  void movt(Register reg, uint32_t immediate, Condition cond = al);
848
849  void bic(Register dst, Register src1, const Operand& src2,
850           SBit s = LeaveCC, Condition cond = al);
851
852  void mvn(Register dst, const Operand& src,
853           SBit s = LeaveCC, Condition cond = al);
854
855  // Shift instructions
856
857  void asr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
858           Condition cond = al) {
859    if (src2.is_reg()) {
860      mov(dst, Operand(src1, ASR, src2.rm()), s, cond);
861    } else {
862      mov(dst, Operand(src1, ASR, src2.immediate()), s, cond);
863    }
864  }
865
866  void lsl(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
867           Condition cond = al) {
868    if (src2.is_reg()) {
869      mov(dst, Operand(src1, LSL, src2.rm()), s, cond);
870    } else {
871      mov(dst, Operand(src1, LSL, src2.immediate()), s, cond);
872    }
873  }
874
875  void lsr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
876           Condition cond = al) {
877    if (src2.is_reg()) {
878      mov(dst, Operand(src1, LSR, src2.rm()), s, cond);
879    } else {
880      mov(dst, Operand(src1, LSR, src2.immediate()), s, cond);
881    }
882  }
883
884  // Multiply instructions
885
886  void mla(Register dst, Register src1, Register src2, Register srcA,
887           SBit s = LeaveCC, Condition cond = al);
888
889  void mls(Register dst, Register src1, Register src2, Register srcA,
890           Condition cond = al);
891
892  void sdiv(Register dst, Register src1, Register src2,
893            Condition cond = al);
894
895  void udiv(Register dst, Register src1, Register src2, Condition cond = al);
896
897  void mul(Register dst, Register src1, Register src2,
898           SBit s = LeaveCC, Condition cond = al);
899
900  void smmla(Register dst, Register src1, Register src2, Register srcA,
901             Condition cond = al);
902
903  void smmul(Register dst, Register src1, Register src2, Condition cond = al);
904
905  void smlal(Register dstL, Register dstH, Register src1, Register src2,
906             SBit s = LeaveCC, Condition cond = al);
907
908  void smull(Register dstL, Register dstH, Register src1, Register src2,
909             SBit s = LeaveCC, Condition cond = al);
910
911  void umlal(Register dstL, Register dstH, Register src1, Register src2,
912             SBit s = LeaveCC, Condition cond = al);
913
914  void umull(Register dstL, Register dstH, Register src1, Register src2,
915             SBit s = LeaveCC, Condition cond = al);
916
917  // Miscellaneous arithmetic instructions
918
919  void clz(Register dst, Register src, Condition cond = al);  // v5 and above
920
921  // Saturating instructions. v6 and above.
922
923  // Unsigned saturate.
924  //
925  // Saturate an optionally shifted signed value to an unsigned range.
926  //
927  //   usat dst, #satpos, src
928  //   usat dst, #satpos, src, lsl #sh
929  //   usat dst, #satpos, src, asr #sh
930  //
931  // Register dst will contain:
932  //
933  //   0,                 if s < 0
934  //   (1 << satpos) - 1, if s > ((1 << satpos) - 1)
935  //   s,                 otherwise
936  //
937  // where s is the contents of src after shifting (if used.)
938  void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
939
940  // Bitfield manipulation instructions. v7 and above.
941
942  void ubfx(Register dst, Register src, int lsb, int width,
943            Condition cond = al);
944
945  void sbfx(Register dst, Register src, int lsb, int width,
946            Condition cond = al);
947
948  void bfc(Register dst, int lsb, int width, Condition cond = al);
949
950  void bfi(Register dst, Register src, int lsb, int width,
951           Condition cond = al);
952
953  void pkhbt(Register dst, Register src1, const Operand& src2,
954             Condition cond = al);
955
956  void pkhtb(Register dst, Register src1, const Operand& src2,
957             Condition cond = al);
958
959  void sxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
960  void sxtab(Register dst, Register src1, Register src2, int rotate = 0,
961             Condition cond = al);
962  void sxth(Register dst, Register src, int rotate = 0, Condition cond = al);
963  void sxtah(Register dst, Register src1, Register src2, int rotate = 0,
964             Condition cond = al);
965
966  void uxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
967  void uxtab(Register dst, Register src1, Register src2, int rotate = 0,
968             Condition cond = al);
969  void uxtb16(Register dst, Register src, int rotate = 0, Condition cond = al);
970  void uxth(Register dst, Register src, int rotate = 0, Condition cond = al);
971  void uxtah(Register dst, Register src1, Register src2, int rotate = 0,
972             Condition cond = al);
973
974  // Reverse the bits in a register.
975  void rbit(Register dst, Register src, Condition cond = al);
976
977  // Status register access instructions
978
979  void mrs(Register dst, SRegister s, Condition cond = al);
980  void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
981
982  // Load/Store instructions
983  void ldr(Register dst, const MemOperand& src, Condition cond = al);
984  void str(Register src, const MemOperand& dst, Condition cond = al);
985  void ldrb(Register dst, const MemOperand& src, Condition cond = al);
986  void strb(Register src, const MemOperand& dst, Condition cond = al);
987  void ldrh(Register dst, const MemOperand& src, Condition cond = al);
988  void strh(Register src, const MemOperand& dst, Condition cond = al);
989  void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
990  void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
991  void ldrd(Register dst1,
992            Register dst2,
993            const MemOperand& src, Condition cond = al);
994  void strd(Register src1,
995            Register src2,
996            const MemOperand& dst, Condition cond = al);
997
998  // Load/Store exclusive instructions
999  void ldrex(Register dst, Register src, Condition cond = al);
1000  void strex(Register src1, Register src2, Register dst, Condition cond = al);
1001  void ldrexb(Register dst, Register src, Condition cond = al);
1002  void strexb(Register src1, Register src2, Register dst, Condition cond = al);
1003  void ldrexh(Register dst, Register src, Condition cond = al);
1004  void strexh(Register src1, Register src2, Register dst, Condition cond = al);
1005
1006  // Preload instructions
1007  void pld(const MemOperand& address);
1008
1009  // Load/Store multiple instructions
1010  void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
1011  void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
1012
1013  // Exception-generating instructions and debugging support
1014  void stop(const char* msg,
1015            Condition cond = al,
1016            int32_t code = kDefaultStopCode);
1017
1018  void bkpt(uint32_t imm16);  // v5 and above
1019  void svc(uint32_t imm24, Condition cond = al);
1020
1021  // Synchronization instructions
1022  void dmb(BarrierOption option);
1023  void dsb(BarrierOption option);
1024  void isb(BarrierOption option);
1025
1026  // Coprocessor instructions
1027
1028  void cdp(Coprocessor coproc, int opcode_1,
1029           CRegister crd, CRegister crn, CRegister crm,
1030           int opcode_2, Condition cond = al);
1031
1032  void cdp2(Coprocessor coproc, int opcode_1,
1033            CRegister crd, CRegister crn, CRegister crm,
1034            int opcode_2);  // v5 and above
1035
1036  void mcr(Coprocessor coproc, int opcode_1,
1037           Register rd, CRegister crn, CRegister crm,
1038           int opcode_2 = 0, Condition cond = al);
1039
1040  void mcr2(Coprocessor coproc, int opcode_1,
1041            Register rd, CRegister crn, CRegister crm,
1042            int opcode_2 = 0);  // v5 and above
1043
1044  void mrc(Coprocessor coproc, int opcode_1,
1045           Register rd, CRegister crn, CRegister crm,
1046           int opcode_2 = 0, Condition cond = al);
1047
1048  void mrc2(Coprocessor coproc, int opcode_1,
1049            Register rd, CRegister crn, CRegister crm,
1050            int opcode_2 = 0);  // v5 and above
1051
1052  void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
1053           LFlag l = Short, Condition cond = al);
1054  void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
1055           LFlag l = Short, Condition cond = al);
1056
1057  void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
1058            LFlag l = Short);  // v5 and above
1059  void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
1060            LFlag l = Short);  // v5 and above
1061
1062  // Support for VFP.
1063  // All these APIs support S0 to S31 and D0 to D31.
1064
1065  void vldr(const DwVfpRegister dst,
1066            const Register base,
1067            int offset,
1068            const Condition cond = al);
1069  void vldr(const DwVfpRegister dst,
1070            const MemOperand& src,
1071            const Condition cond = al);
1072
1073  void vldr(const SwVfpRegister dst,
1074            const Register base,
1075            int offset,
1076            const Condition cond = al);
1077  void vldr(const SwVfpRegister dst,
1078            const MemOperand& src,
1079            const Condition cond = al);
1080
1081  void vstr(const DwVfpRegister src,
1082            const Register base,
1083            int offset,
1084            const Condition cond = al);
1085  void vstr(const DwVfpRegister src,
1086            const MemOperand& dst,
1087            const Condition cond = al);
1088
1089  void vstr(const SwVfpRegister src,
1090            const Register base,
1091            int offset,
1092            const Condition cond = al);
1093  void vstr(const SwVfpRegister src,
1094            const MemOperand& dst,
1095            const Condition cond = al);
1096
1097  void vldm(BlockAddrMode am,
1098            Register base,
1099            DwVfpRegister first,
1100            DwVfpRegister last,
1101            Condition cond = al);
1102
1103  void vstm(BlockAddrMode am,
1104            Register base,
1105            DwVfpRegister first,
1106            DwVfpRegister last,
1107            Condition cond = al);
1108
1109  void vldm(BlockAddrMode am,
1110            Register base,
1111            SwVfpRegister first,
1112            SwVfpRegister last,
1113            Condition cond = al);
1114
1115  void vstm(BlockAddrMode am,
1116            Register base,
1117            SwVfpRegister first,
1118            SwVfpRegister last,
1119            Condition cond = al);
1120
1121  void vmov(const SwVfpRegister dst, float imm);
1122  void vmov(const DwVfpRegister dst,
1123            double imm,
1124            const Register scratch = no_reg);
1125  void vmov(const SwVfpRegister dst,
1126            const SwVfpRegister src,
1127            const Condition cond = al);
1128  void vmov(const DwVfpRegister dst,
1129            const DwVfpRegister src,
1130            const Condition cond = al);
1131  void vmov(const DwVfpRegister dst,
1132            const VmovIndex index,
1133            const Register src,
1134            const Condition cond = al);
1135  void vmov(const Register dst,
1136            const VmovIndex index,
1137            const DwVfpRegister src,
1138            const Condition cond = al);
1139  void vmov(const DwVfpRegister dst,
1140            const Register src1,
1141            const Register src2,
1142            const Condition cond = al);
1143  void vmov(const Register dst1,
1144            const Register dst2,
1145            const DwVfpRegister src,
1146            const Condition cond = al);
1147  void vmov(const SwVfpRegister dst,
1148            const Register src,
1149            const Condition cond = al);
1150  void vmov(const Register dst,
1151            const SwVfpRegister src,
1152            const Condition cond = al);
1153  void vcvt_f64_s32(const DwVfpRegister dst,
1154                    const SwVfpRegister src,
1155                    VFPConversionMode mode = kDefaultRoundToZero,
1156                    const Condition cond = al);
1157  void vcvt_f32_s32(const SwVfpRegister dst,
1158                    const SwVfpRegister src,
1159                    VFPConversionMode mode = kDefaultRoundToZero,
1160                    const Condition cond = al);
1161  void vcvt_f64_u32(const DwVfpRegister dst,
1162                    const SwVfpRegister src,
1163                    VFPConversionMode mode = kDefaultRoundToZero,
1164                    const Condition cond = al);
1165  void vcvt_f32_u32(const SwVfpRegister dst,
1166                    const SwVfpRegister src,
1167                    VFPConversionMode mode = kDefaultRoundToZero,
1168                    const Condition cond = al);
1169  void vcvt_s32_f32(const SwVfpRegister dst,
1170                    const SwVfpRegister src,
1171                    VFPConversionMode mode = kDefaultRoundToZero,
1172                    const Condition cond = al);
1173  void vcvt_u32_f32(const SwVfpRegister dst,
1174                    const SwVfpRegister src,
1175                    VFPConversionMode mode = kDefaultRoundToZero,
1176                    const Condition cond = al);
1177  void vcvt_s32_f64(const SwVfpRegister dst,
1178                    const DwVfpRegister src,
1179                    VFPConversionMode mode = kDefaultRoundToZero,
1180                    const Condition cond = al);
1181  void vcvt_u32_f64(const SwVfpRegister dst,
1182                    const DwVfpRegister src,
1183                    VFPConversionMode mode = kDefaultRoundToZero,
1184                    const Condition cond = al);
1185  void vcvt_f64_f32(const DwVfpRegister dst,
1186                    const SwVfpRegister src,
1187                    VFPConversionMode mode = kDefaultRoundToZero,
1188                    const Condition cond = al);
1189  void vcvt_f32_f64(const SwVfpRegister dst,
1190                    const DwVfpRegister src,
1191                    VFPConversionMode mode = kDefaultRoundToZero,
1192                    const Condition cond = al);
1193  void vcvt_f64_s32(const DwVfpRegister dst,
1194                    int fraction_bits,
1195                    const Condition cond = al);
1196
1197  void vmrs(const Register dst, const Condition cond = al);
1198  void vmsr(const Register dst, const Condition cond = al);
1199
1200  void vneg(const DwVfpRegister dst,
1201            const DwVfpRegister src,
1202            const Condition cond = al);
1203  void vneg(const SwVfpRegister dst, const SwVfpRegister src,
1204            const Condition cond = al);
1205  void vabs(const DwVfpRegister dst,
1206            const DwVfpRegister src,
1207            const Condition cond = al);
1208  void vabs(const SwVfpRegister dst, const SwVfpRegister src,
1209            const Condition cond = al);
1210  void vadd(const DwVfpRegister dst,
1211            const DwVfpRegister src1,
1212            const DwVfpRegister src2,
1213            const Condition cond = al);
1214  void vadd(const SwVfpRegister dst, const SwVfpRegister src1,
1215            const SwVfpRegister src2, const Condition cond = al);
1216  void vsub(const DwVfpRegister dst,
1217            const DwVfpRegister src1,
1218            const DwVfpRegister src2,
1219            const Condition cond = al);
1220  void vsub(const SwVfpRegister dst, const SwVfpRegister src1,
1221            const SwVfpRegister src2, const Condition cond = al);
1222  void vmul(const DwVfpRegister dst,
1223            const DwVfpRegister src1,
1224            const DwVfpRegister src2,
1225            const Condition cond = al);
1226  void vmul(const SwVfpRegister dst, const SwVfpRegister src1,
1227            const SwVfpRegister src2, const Condition cond = al);
1228  void vmla(const DwVfpRegister dst,
1229            const DwVfpRegister src1,
1230            const DwVfpRegister src2,
1231            const Condition cond = al);
1232  void vmla(const SwVfpRegister dst, const SwVfpRegister src1,
1233            const SwVfpRegister src2, const Condition cond = al);
1234  void vmls(const DwVfpRegister dst,
1235            const DwVfpRegister src1,
1236            const DwVfpRegister src2,
1237            const Condition cond = al);
1238  void vmls(const SwVfpRegister dst, const SwVfpRegister src1,
1239            const SwVfpRegister src2, const Condition cond = al);
1240  void vdiv(const DwVfpRegister dst,
1241            const DwVfpRegister src1,
1242            const DwVfpRegister src2,
1243            const Condition cond = al);
1244  void vdiv(const SwVfpRegister dst, const SwVfpRegister src1,
1245            const SwVfpRegister src2, const Condition cond = al);
1246  void vcmp(const DwVfpRegister src1,
1247            const DwVfpRegister src2,
1248            const Condition cond = al);
1249  void vcmp(const SwVfpRegister src1, const SwVfpRegister src2,
1250            const Condition cond = al);
1251  void vcmp(const DwVfpRegister src1,
1252            const double src2,
1253            const Condition cond = al);
1254  void vcmp(const SwVfpRegister src1, const float src2,
1255            const Condition cond = al);
1256
1257  // VSEL supports cond in {eq, ne, ge, lt, gt, le, vs, vc}.
1258  void vsel(const Condition cond,
1259            const DwVfpRegister dst,
1260            const DwVfpRegister src1,
1261            const DwVfpRegister src2);
1262  void vsel(const Condition cond,
1263            const SwVfpRegister dst,
1264            const SwVfpRegister src1,
1265            const SwVfpRegister src2);
1266
1267  void vsqrt(const DwVfpRegister dst,
1268             const DwVfpRegister src,
1269             const Condition cond = al);
1270  void vsqrt(const SwVfpRegister dst, const SwVfpRegister src,
1271             const Condition cond = al);
1272
1273  // ARMv8 rounding instructions.
1274  void vrinta(const SwVfpRegister dst, const SwVfpRegister src);
1275  void vrinta(const DwVfpRegister dst, const DwVfpRegister src);
1276  void vrintn(const SwVfpRegister dst, const SwVfpRegister src);
1277  void vrintn(const DwVfpRegister dst, const DwVfpRegister src);
1278  void vrintm(const SwVfpRegister dst, const SwVfpRegister src);
1279  void vrintm(const DwVfpRegister dst, const DwVfpRegister src);
1280  void vrintp(const SwVfpRegister dst, const SwVfpRegister src);
1281  void vrintp(const DwVfpRegister dst, const DwVfpRegister src);
1282  void vrintz(const SwVfpRegister dst, const SwVfpRegister src,
1283              const Condition cond = al);
1284  void vrintz(const DwVfpRegister dst, const DwVfpRegister src,
1285              const Condition cond = al);
1286
1287  // Support for NEON.
1288  // All these APIs support D0 to D31 and Q0 to Q15.
1289
1290  void vld1(NeonSize size,
1291            const NeonListOperand& dst,
1292            const NeonMemOperand& src);
1293  void vst1(NeonSize size,
1294            const NeonListOperand& src,
1295            const NeonMemOperand& dst);
1296  void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
1297
1298  // Pseudo instructions
1299
1300  // Different nop operations are used by the code generator to detect certain
1301  // states of the generated code.
1302  enum NopMarkerTypes {
1303    NON_MARKING_NOP = 0,
1304    DEBUG_BREAK_NOP,
1305    // IC markers.
1306    PROPERTY_ACCESS_INLINED,
1307    PROPERTY_ACCESS_INLINED_CONTEXT,
1308    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1309    // Helper values.
1310    LAST_CODE_MARKER,
1311    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1312  };
1313
1314  void nop(int type = 0);   // 0 is the default non-marking type.
1315
1316  void push(Register src, Condition cond = al) {
1317    str(src, MemOperand(sp, 4, NegPreIndex), cond);
1318  }
1319
1320  void pop(Register dst, Condition cond = al) {
1321    ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1322  }
1323
1324  void pop() {
1325    add(sp, sp, Operand(kPointerSize));
1326  }
1327
1328  void vpush(DwVfpRegister src, Condition cond = al) {
1329    vstm(db_w, sp, src, src, cond);
1330  }
1331
1332  void vpush(SwVfpRegister src, Condition cond = al) {
1333    vstm(db_w, sp, src, src, cond);
1334  }
1335
1336  void vpop(DwVfpRegister dst, Condition cond = al) {
1337    vldm(ia_w, sp, dst, dst, cond);
1338  }
1339
1340  // Jump unconditionally to given label.
1341  void jmp(Label* L) { b(L, al); }
1342
1343  // Check the code size generated from label to here.
1344  int SizeOfCodeGeneratedSince(Label* label) {
1345    return pc_offset() - label->pos();
1346  }
1347
1348  // Check the number of instructions generated from label to here.
1349  int InstructionsGeneratedSince(Label* label) {
1350    return SizeOfCodeGeneratedSince(label) / kInstrSize;
1351  }
1352
1353  // Check whether an immediate fits an addressing mode 1 instruction.
1354  static bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1355
1356  // Check whether an immediate fits an addressing mode 2 instruction.
1357  bool ImmediateFitsAddrMode2Instruction(int32_t imm32);
1358
1359  // Class for scoping postponing the constant pool generation.
1360  class BlockConstPoolScope {
1361   public:
1362    explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1363      assem_->StartBlockConstPool();
1364    }
1365    ~BlockConstPoolScope() {
1366      assem_->EndBlockConstPool();
1367    }
1368
1369   private:
1370    Assembler* assem_;
1371
1372    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1373  };
1374
1375  // Debugging
1376
1377  // Mark generator continuation.
1378  void RecordGeneratorContinuation();
1379
1380  // Mark address of a debug break slot.
1381  void RecordDebugBreakSlot(RelocInfo::Mode mode);
1382
1383  // Record the AST id of the CallIC being compiled, so that it can be placed
1384  // in the relocation information.
1385  void SetRecordedAstId(TypeFeedbackId ast_id) {
1386    DCHECK(recorded_ast_id_.IsNone());
1387    recorded_ast_id_ = ast_id;
1388  }
1389
1390  TypeFeedbackId RecordedAstId() {
1391    DCHECK(!recorded_ast_id_.IsNone());
1392    return recorded_ast_id_;
1393  }
1394
1395  void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
1396
1397  // Record a comment relocation entry that can be used by a disassembler.
1398  // Use --code-comments to enable.
1399  void RecordComment(const char* msg);
1400
1401  // Record a deoptimization reason that can be used by a log or cpu profiler.
1402  // Use --trace-deopt to enable.
1403  void RecordDeoptReason(const int reason, int raw_position, int id);
1404
1405  // Record the emission of a constant pool.
1406  //
1407  // The emission of constant pool depends on the size of the code generated and
1408  // the number of RelocInfo recorded.
1409  // The Debug mechanism needs to map code offsets between two versions of a
1410  // function, compiled with and without debugger support (see for example
1411  // Debug::PrepareForBreakPoints()).
1412  // Compiling functions with debugger support generates additional code
1413  // (DebugCodegen::GenerateSlot()). This may affect the emission of the
1414  // constant pools and cause the version of the code with debugger support to
1415  // have constant pools generated in different places.
1416  // Recording the position and size of emitted constant pools allows to
1417  // correctly compute the offset mappings between the different versions of a
1418  // function in all situations.
1419  //
1420  // The parameter indicates the size of the constant pool (in bytes), including
1421  // the marker and branch over the data.
1422  void RecordConstPool(int size);
1423
1424  // Writes a single byte or word of data in the code stream.  Used
1425  // for inline tables, e.g., jump-tables. CheckConstantPool() should be
1426  // called before any use of db/dd/dq/dp to ensure that constant pools
1427  // are not emitted as part of the tables generated.
1428  void db(uint8_t data);
1429  void dd(uint32_t data);
1430  void dq(uint64_t data);
1431  void dp(uintptr_t data) { dd(data); }
1432
1433  // Emits the address of the code stub's first instruction.
1434  void emit_code_stub_address(Code* stub);
1435
1436  AssemblerPositionsRecorder* positions_recorder() {
1437    return &positions_recorder_;
1438  }
1439
1440  // Read/patch instructions
1441  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1442  void instr_at_put(int pos, Instr instr) {
1443    *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1444  }
1445  static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1446  static void instr_at_put(byte* pc, Instr instr) {
1447    *reinterpret_cast<Instr*>(pc) = instr;
1448  }
1449  static Condition GetCondition(Instr instr);
1450  static bool IsBranch(Instr instr);
1451  static int GetBranchOffset(Instr instr);
1452  static bool IsLdrRegisterImmediate(Instr instr);
1453  static bool IsVldrDRegisterImmediate(Instr instr);
1454  static Instr GetConsantPoolLoadPattern();
1455  static Instr GetConsantPoolLoadMask();
1456  static bool IsLdrPpRegOffset(Instr instr);
1457  static Instr GetLdrPpRegOffsetPattern();
1458  static bool IsLdrPpImmediateOffset(Instr instr);
1459  static bool IsVldrDPpImmediateOffset(Instr instr);
1460  static int GetLdrRegisterImmediateOffset(Instr instr);
1461  static int GetVldrDRegisterImmediateOffset(Instr instr);
1462  static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
1463  static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
1464  static bool IsStrRegisterImmediate(Instr instr);
1465  static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1466  static bool IsAddRegisterImmediate(Instr instr);
1467  static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
1468  static Register GetRd(Instr instr);
1469  static Register GetRn(Instr instr);
1470  static Register GetRm(Instr instr);
1471  static bool IsPush(Instr instr);
1472  static bool IsPop(Instr instr);
1473  static bool IsStrRegFpOffset(Instr instr);
1474  static bool IsLdrRegFpOffset(Instr instr);
1475  static bool IsStrRegFpNegOffset(Instr instr);
1476  static bool IsLdrRegFpNegOffset(Instr instr);
1477  static bool IsLdrPcImmediateOffset(Instr instr);
1478  static bool IsVldrDPcImmediateOffset(Instr instr);
1479  static bool IsBlxReg(Instr instr);
1480  static bool IsBlxIp(Instr instr);
1481  static bool IsTstImmediate(Instr instr);
1482  static bool IsCmpRegister(Instr instr);
1483  static bool IsCmpImmediate(Instr instr);
1484  static Register GetCmpImmediateRegister(Instr instr);
1485  static int GetCmpImmediateRawImmediate(Instr instr);
1486  static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1487  static bool IsMovImmed(Instr instr);
1488  static bool IsOrrImmed(Instr instr);
1489  static bool IsMovT(Instr instr);
1490  static Instr GetMovTPattern();
1491  static bool IsMovW(Instr instr);
1492  static Instr GetMovWPattern();
1493  static Instr EncodeMovwImmediate(uint32_t immediate);
1494  static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate);
1495  static int DecodeShiftImm(Instr instr);
1496  static Instr PatchShiftImm(Instr instr, int immed);
1497
1498  // Constants in pools are accessed via pc relative addressing, which can
1499  // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
1500  // PC-relative loads, thereby defining a maximum distance between the
1501  // instruction and the accessed constant.
1502  static const int kMaxDistToIntPool = 4*KB;
1503  static const int kMaxDistToFPPool = 1*KB;
1504  // All relocations could be integer, it therefore acts as the limit.
1505  static const int kMinNumPendingConstants = 4;
1506  static const int kMaxNumPending32Constants = kMaxDistToIntPool / kInstrSize;
1507  static const int kMaxNumPending64Constants = kMaxDistToFPPool / kInstrSize;
1508
1509  // Postpone the generation of the constant pool for the specified number of
1510  // instructions.
1511  void BlockConstPoolFor(int instructions);
1512
1513  // Check if is time to emit a constant pool.
1514  void CheckConstPool(bool force_emit, bool require_jump);
1515
1516  void MaybeCheckConstPool() {
1517    if (pc_offset() >= next_buffer_check_) {
1518      CheckConstPool(false, true);
1519    }
1520  }
1521
1522  int EmitEmbeddedConstantPool() {
1523    DCHECK(FLAG_enable_embedded_constant_pool);
1524    return constant_pool_builder_.Emit(this);
1525  }
1526
1527  bool ConstantPoolAccessIsInOverflow() const {
1528    return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
1529           ConstantPoolEntry::OVERFLOWED;
1530  }
1531
1532  void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
1533                                          ConstantPoolEntry::Access access,
1534                                          ConstantPoolEntry::Type type);
1535
1536 protected:
1537  // Relocation for a type-recording IC has the AST id added to it.  This
1538  // member variable is a way to pass the information from the call site to
1539  // the relocation info.
1540  TypeFeedbackId recorded_ast_id_;
1541
1542  int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1543
1544  // Decode branch instruction at pos and return branch target pos
1545  int target_at(int pos);
1546
1547  // Patch branch instruction at pos to branch to given branch target pos
1548  void target_at_put(int pos, int target_pos);
1549
1550  // Prevent contant pool emission until EndBlockConstPool is called.
1551  // Call to this function can be nested but must be followed by an equal
1552  // number of call to EndBlockConstpool.
1553  void StartBlockConstPool() {
1554    if (const_pool_blocked_nesting_++ == 0) {
1555      // Prevent constant pool checks happening by setting the next check to
1556      // the biggest possible offset.
1557      next_buffer_check_ = kMaxInt;
1558    }
1559  }
1560
1561  // Resume constant pool emission. Need to be called as many time as
1562  // StartBlockConstPool to have an effect.
1563  void EndBlockConstPool() {
1564    if (--const_pool_blocked_nesting_ == 0) {
1565#ifdef DEBUG
1566      // Max pool start (if we need a jump and an alignment).
1567      int start = pc_offset() + kInstrSize + 2 * kPointerSize;
1568      // Check the constant pool hasn't been blocked for too long.
1569      DCHECK(pending_32_bit_constants_.empty() ||
1570             (start + pending_64_bit_constants_.size() * kDoubleSize <
1571              (first_const_pool_32_use_ + kMaxDistToIntPool)));
1572      DCHECK(pending_64_bit_constants_.empty() ||
1573             (start < (first_const_pool_64_use_ + kMaxDistToFPPool)));
1574#endif
1575      // Two cases:
1576      //  * no_const_pool_before_ >= next_buffer_check_ and the emission is
1577      //    still blocked
1578      //  * no_const_pool_before_ < next_buffer_check_ and the next emit will
1579      //    trigger a check.
1580      next_buffer_check_ = no_const_pool_before_;
1581    }
1582  }
1583
1584  bool is_const_pool_blocked() const {
1585    return (const_pool_blocked_nesting_ > 0) ||
1586           (pc_offset() < no_const_pool_before_);
1587  }
1588
1589 private:
1590  int next_buffer_check_;  // pc offset of next buffer check
1591
1592  // Code generation
1593  // The relocation writer's position is at least kGap bytes below the end of
1594  // the generated instructions. This is so that multi-instruction sequences do
1595  // not have to check for overflow. The same is true for writes of large
1596  // relocation info entries.
1597  static const int kGap = 32;
1598
1599  // Constant pool generation
1600  // Pools are emitted in the instruction stream, preferably after unconditional
1601  // jumps or after returns from functions (in dead code locations).
1602  // If a long code sequence does not contain unconditional jumps, it is
1603  // necessary to emit the constant pool before the pool gets too far from the
1604  // location it is accessed from. In this case, we emit a jump over the emitted
1605  // constant pool.
1606  // Constants in the pool may be addresses of functions that gets relocated;
1607  // if so, a relocation info entry is associated to the constant pool entry.
1608
1609  // Repeated checking whether the constant pool should be emitted is rather
1610  // expensive. By default we only check again once a number of instructions
1611  // has been generated. That also means that the sizing of the buffers is not
1612  // an exact science, and that we rely on some slop to not overrun buffers.
1613  static const int kCheckPoolIntervalInst = 32;
1614  static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
1615
1616
1617  // Emission of the constant pool may be blocked in some code sequences.
1618  int const_pool_blocked_nesting_;  // Block emission if this is not zero.
1619  int no_const_pool_before_;  // Block emission before this pc offset.
1620
1621  // Keep track of the first instruction requiring a constant pool entry
1622  // since the previous constant pool was emitted.
1623  int first_const_pool_32_use_;
1624  int first_const_pool_64_use_;
1625
1626  // Relocation info generation
1627  // Each relocation is encoded as a variable size value
1628  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1629  RelocInfoWriter reloc_info_writer;
1630
1631  // ConstantPoolEntry records are used during code generation as temporary
1632  // containers for constants and code target addresses until they are emitted
1633  // to the constant pool. These records are temporarily stored in a separate
1634  // buffer until a constant pool is emitted.
1635  // If every instruction in a long sequence is accessing the pool, we need one
1636  // pending relocation entry per instruction.
1637
1638  // The buffers of pending constant pool entries.
1639  std::vector<ConstantPoolEntry> pending_32_bit_constants_;
1640  std::vector<ConstantPoolEntry> pending_64_bit_constants_;
1641
1642  ConstantPoolBuilder constant_pool_builder_;
1643
1644  // The bound position, before this we cannot do instruction elimination.
1645  int last_bound_pos_;
1646
1647  // Code emission
1648  inline void CheckBuffer();
1649  void GrowBuffer();
1650  inline void emit(Instr x);
1651
1652  // 32-bit immediate values
1653  void move_32_bit_immediate(Register rd,
1654                             const Operand& x,
1655                             Condition cond = al);
1656
1657  // Instruction generation
1658  void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1659  void addrmod2(Instr instr, Register rd, const MemOperand& x);
1660  void addrmod3(Instr instr, Register rd, const MemOperand& x);
1661  void addrmod4(Instr instr, Register rn, RegList rl);
1662  void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1663
1664  // Labels
1665  void print(Label* L);
1666  void bind_to(Label* L, int pos);
1667  void next(Label* L);
1668
1669  // Record reloc info for current pc_
1670  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1671  ConstantPoolEntry::Access ConstantPoolAddEntry(int position,
1672                                                 RelocInfo::Mode rmode,
1673                                                 intptr_t value);
1674  ConstantPoolEntry::Access ConstantPoolAddEntry(int position, double value);
1675
1676  friend class RelocInfo;
1677  friend class CodePatcher;
1678  friend class BlockConstPoolScope;
1679  AssemblerPositionsRecorder positions_recorder_;
1680  friend class AssemblerPositionsRecorder;
1681  friend class EnsureSpace;
1682};
1683
1684
1685class EnsureSpace BASE_EMBEDDED {
1686 public:
1687  explicit EnsureSpace(Assembler* assembler) {
1688    assembler->CheckBuffer();
1689  }
1690};
1691
1692
1693}  // namespace internal
1694}  // namespace v8
1695
1696#endif  // V8_ARM_ASSEMBLER_ARM_H_
1697