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