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