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