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 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 
108 struct 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 
from_codeRegister119   static Register from_code(int code) {
120     DCHECK(code >= 0);
121     DCHECK(code < kNumRegisters);
122     Register r = {code};
123     return r;
124   }
is_validRegister125   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
isRegister126   bool is(Register reg) const { return reg_code == reg.reg_code; }
codeRegister127   int code() const {
128     DCHECK(is_valid());
129     return reg_code;
130   }
bitRegister131   int bit() const {
132     DCHECK(is_valid());
133     return 1 << reg_code;
134   }
set_codeRegister135   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};
148 GENERAL_REGISTERS(DECLARE_REGISTER)
149 #undef DECLARE_REGISTER
150 const Register no_reg = {Register::kCode_no_reg};
151 
152 static const bool kSimpleFPAliasing = false;
153 
154 // Single word VFP register.
155 struct 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 
is_validSwVfpRegister168   bool is_valid() const { return 0 <= reg_code && reg_code < 32; }
isSwVfpRegister169   bool is(SwVfpRegister reg) const { return reg_code == reg.reg_code; }
codeSwVfpRegister170   int code() const {
171     DCHECK(is_valid());
172     return reg_code;
173   }
bitSwVfpRegister174   int bit() const {
175     DCHECK(is_valid());
176     return 1 << reg_code;
177   }
from_codeSwVfpRegister178   static SwVfpRegister from_code(int code) {
179     SwVfpRegister r = {code};
180     return r;
181   }
split_codeSwVfpRegister182   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 
191 typedef SwVfpRegister FloatRegister;
192 
193 // Double word VFP register.
194 struct 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 
is_validDwVfpRegister213   bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
isDwVfpRegister214   bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
codeDwVfpRegister215   int code() const {
216     DCHECK(is_valid());
217     return reg_code;
218   }
bitDwVfpRegister219   int bit() const {
220     DCHECK(is_valid());
221     return 1 << reg_code;
222   }
223 
from_codeDwVfpRegister224   static DwVfpRegister from_code(int code) {
225     DwVfpRegister r = {code};
226     return r;
227   }
split_codeDwVfpRegister228   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 
238 typedef DwVfpRegister DoubleRegister;
239 
240 
241 // Double word VFP register d0-15.
242 struct LowDwVfpRegister {
243  public:
244   static const int kMaxNumLowRegisters = 16;
DwVfpRegisterLowDwVfpRegister245   operator DwVfpRegister() const {
246     DwVfpRegister r = { reg_code };
247     return r;
248   }
from_codeLowDwVfpRegister249   static LowDwVfpRegister from_code(int code) {
250     LowDwVfpRegister r = { code };
251     return r;
252   }
253 
is_validLowDwVfpRegister254   bool is_valid() const {
255     return 0 <= reg_code && reg_code < kMaxNumLowRegisters;
256   }
isLowDwVfpRegister257   bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
isLowDwVfpRegister258   bool is(LowDwVfpRegister reg) const { return reg_code == reg.reg_code; }
codeLowDwVfpRegister259   int code() const {
260     DCHECK(is_valid());
261     return reg_code;
262   }
lowLowDwVfpRegister263   SwVfpRegister low() const {
264     SwVfpRegister reg;
265     reg.reg_code = reg_code * 2;
266 
267     DCHECK(reg.is_valid());
268     return reg;
269   }
highLowDwVfpRegister270   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.
283 struct QwNeonRegister {
284   static const int kMaxNumRegisters = 16;
285 
from_codeQwNeonRegister286   static QwNeonRegister from_code(int code) {
287     QwNeonRegister r = { code };
288     return r;
289   }
290 
is_validQwNeonRegister291   bool is_valid() const {
292     return (0 <= reg_code) && (reg_code < kMaxNumRegisters);
293   }
isQwNeonRegister294   bool is(QwNeonRegister reg) const { return reg_code == reg.reg_code; }
codeQwNeonRegister295   int code() const {
296     DCHECK(is_valid());
297     return reg_code;
298   }
split_codeQwNeonRegister299   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 
310 typedef QwNeonRegister QuadRegister;
311 
312 typedef 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)".
316 const SwVfpRegister s0  = {  0 };
317 const SwVfpRegister s1  = {  1 };
318 const SwVfpRegister s2  = {  2 };
319 const SwVfpRegister s3  = {  3 };
320 const SwVfpRegister s4  = {  4 };
321 const SwVfpRegister s5  = {  5 };
322 const SwVfpRegister s6  = {  6 };
323 const SwVfpRegister s7  = {  7 };
324 const SwVfpRegister s8  = {  8 };
325 const SwVfpRegister s9  = {  9 };
326 const SwVfpRegister s10 = { 10 };
327 const SwVfpRegister s11 = { 11 };
328 const SwVfpRegister s12 = { 12 };
329 const SwVfpRegister s13 = { 13 };
330 const SwVfpRegister s14 = { 14 };
331 const SwVfpRegister s15 = { 15 };
332 const SwVfpRegister s16 = { 16 };
333 const SwVfpRegister s17 = { 17 };
334 const SwVfpRegister s18 = { 18 };
335 const SwVfpRegister s19 = { 19 };
336 const SwVfpRegister s20 = { 20 };
337 const SwVfpRegister s21 = { 21 };
338 const SwVfpRegister s22 = { 22 };
339 const SwVfpRegister s23 = { 23 };
340 const SwVfpRegister s24 = { 24 };
341 const SwVfpRegister s25 = { 25 };
342 const SwVfpRegister s26 = { 26 };
343 const SwVfpRegister s27 = { 27 };
344 const SwVfpRegister s28 = { 28 };
345 const SwVfpRegister s29 = { 29 };
346 const SwVfpRegister s30 = { 30 };
347 const SwVfpRegister s31 = { 31 };
348 
349 const DwVfpRegister no_dreg = { -1 };
350 const LowDwVfpRegister d0 = { 0 };
351 const LowDwVfpRegister d1 = { 1 };
352 const LowDwVfpRegister d2 = { 2 };
353 const LowDwVfpRegister d3 = { 3 };
354 const LowDwVfpRegister d4 = { 4 };
355 const LowDwVfpRegister d5 = { 5 };
356 const LowDwVfpRegister d6 = { 6 };
357 const LowDwVfpRegister d7 = { 7 };
358 const LowDwVfpRegister d8 = { 8 };
359 const LowDwVfpRegister d9 = { 9 };
360 const LowDwVfpRegister d10 = { 10 };
361 const LowDwVfpRegister d11 = { 11 };
362 const LowDwVfpRegister d12 = { 12 };
363 const LowDwVfpRegister d13 = { 13 };
364 const LowDwVfpRegister d14 = { 14 };
365 const LowDwVfpRegister d15 = { 15 };
366 const DwVfpRegister d16 = { 16 };
367 const DwVfpRegister d17 = { 17 };
368 const DwVfpRegister d18 = { 18 };
369 const DwVfpRegister d19 = { 19 };
370 const DwVfpRegister d20 = { 20 };
371 const DwVfpRegister d21 = { 21 };
372 const DwVfpRegister d22 = { 22 };
373 const DwVfpRegister d23 = { 23 };
374 const DwVfpRegister d24 = { 24 };
375 const DwVfpRegister d25 = { 25 };
376 const DwVfpRegister d26 = { 26 };
377 const DwVfpRegister d27 = { 27 };
378 const DwVfpRegister d28 = { 28 };
379 const DwVfpRegister d29 = { 29 };
380 const DwVfpRegister d30 = { 30 };
381 const DwVfpRegister d31 = { 31 };
382 
383 const QwNeonRegister q0  = {  0 };
384 const QwNeonRegister q1  = {  1 };
385 const QwNeonRegister q2  = {  2 };
386 const QwNeonRegister q3  = {  3 };
387 const QwNeonRegister q4  = {  4 };
388 const QwNeonRegister q5  = {  5 };
389 const QwNeonRegister q6  = {  6 };
390 const QwNeonRegister q7  = {  7 };
391 const QwNeonRegister q8  = {  8 };
392 const QwNeonRegister q9  = {  9 };
393 const QwNeonRegister q10 = { 10 };
394 const QwNeonRegister q11 = { 11 };
395 const QwNeonRegister q12 = { 12 };
396 const QwNeonRegister q13 = { 13 };
397 const QwNeonRegister q14 = { 14 };
398 const 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
411 struct CRegister {
is_validCRegister412   bool is_valid() const { return 0 <= reg_code && reg_code < 16; }
isCRegister413   bool is(CRegister creg) const { return reg_code == creg.reg_code; }
codeCRegister414   int code() const {
415     DCHECK(is_valid());
416     return reg_code;
417   }
bitCRegister418   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 
428 const CRegister no_creg = { -1 };
429 
430 const CRegister cr0  = {  0 };
431 const CRegister cr1  = {  1 };
432 const CRegister cr2  = {  2 };
433 const CRegister cr3  = {  3 };
434 const CRegister cr4  = {  4 };
435 const CRegister cr5  = {  5 };
436 const CRegister cr6  = {  6 };
437 const CRegister cr7  = {  7 };
438 const CRegister cr8  = {  8 };
439 const CRegister cr9  = {  9 };
440 const CRegister cr10 = { 10 };
441 const CRegister cr11 = { 11 };
442 const CRegister cr12 = { 12 };
443 const CRegister cr13 = { 13 };
444 const CRegister cr14 = { 14 };
445 const CRegister cr15 = { 15 };
446 
447 
448 // Coprocessor number
449 enum 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
473 class Operand BASE_EMBEDDED {
474  public:
475   // immediate
476   INLINE(explicit Operand(int32_t immediate,
477          RelocInfo::Mode rmode = RelocInfo::NONE32));
INLINE(static Operand Zero ())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);
INLINE(static Operand SmiUntag (Register rm))490   INLINE(static Operand SmiUntag(Register rm)) {
491     return Operand(rm, ASR, kSmiTagSize);
492   }
INLINE(static Operand PointerOffsetFromSmiKey (Register key))493   INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
494     STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
495     return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
496   }
INLINE(static Operand DoubleOffsetFromSmiKey (Register key))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 
immediate()522   inline int32_t immediate() const {
523     DCHECK(!rm_.is_valid());
524     return imm32_;
525   }
526 
rm()527   Register rm() const { return rm_; }
rs()528   Register rs() const { return rs_; }
shift_op()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
544 class 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 
set_offset(int32_t offset)570   void set_offset(int32_t offset) {
571       DCHECK(rm_.is(no_reg));
572       offset_ = offset;
573   }
574 
offset()575   uint32_t offset() const {
576       DCHECK(rm_.is(no_reg));
577       return offset_;
578   }
579 
rn()580   Register rn() const { return rn_; }
rm()581   Register rm() const { return rm_; }
am()582   AddrMode am() const { return am_; }
583 
OffsetIsUint12Encodable()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
602 class 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 
rn()611   Register rn() const { return rn_; }
rm()612   Register rm() const { return rm_; }
align()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
625 class NeonListOperand BASE_EMBEDDED {
626  public:
627   explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
base()628   DoubleRegister base() const { return base_; }
type()629   NeonListType type() const { return type_; }
630  private:
631   DoubleRegister base_;
632   NeonListType type_;
633 };
634 
635 
636 struct VmovIndex {
637   unsigned char index;
638 };
639 const VmovIndex VmovIndexLo = { 0 };
640 const VmovIndex VmovIndexHi = { 1 };
641 
642 class 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));
INLINE(static Address target_address_at (Address pc,Code * code))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   }
INLINE(static void set_target_address_at (Isolate * isolate,Address pc,Code * code,Address target,ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED))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);
b(Condition cond,Label * L)777   void b(Condition cond, Label* L) { b(L, cond); }
778   void bl(Label* L, Condition cond = al);
bl(Condition cond,Label * L)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 
pop()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.
jmp(Label * L)1362   void jmp(Label* L) { b(L, al); }
1363 
1364   // Check the code size generated from label to here.
SizeOfCodeGeneratedSince(Label * label)1365   int SizeOfCodeGeneratedSince(Label* label) {
1366     return pc_offset() - label->pos();
1367   }
1368 
1369   // Check the number of instructions generated from label to here.
InstructionsGeneratedSince(Label * label)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:
BlockConstPoolScope(Assembler * assem)1383     explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1384       assem_->StartBlockConstPool();
1385     }
~BlockConstPoolScope()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.
SetRecordedAstId(TypeFeedbackId ast_id)1406   void SetRecordedAstId(TypeFeedbackId ast_id) {
1407     DCHECK(recorded_ast_id_.IsNone());
1408     recorded_ast_id_ = ast_id;
1409   }
1410 
RecordedAstId()1411   TypeFeedbackId RecordedAstId() {
1412     DCHECK(!recorded_ast_id_.IsNone());
1413     return recorded_ast_id_;
1414   }
1415 
ClearRecordedAstId()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);
dp(uintptr_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
instr_at(int pos)1459   Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
instr_at_put(int pos,Instr instr)1460   void instr_at_put(int pos, Instr instr) {
1461     *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1462   }
instr_at(byte * pc)1463   static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
instr_at_put(byte * pc,Instr instr)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 
MaybeCheckConstPool()1534   void MaybeCheckConstPool() {
1535     if (pc_offset() >= next_buffer_check_) {
1536       CheckConstPool(false, true);
1537     }
1538   }
1539 
EmitEmbeddedConstantPool()1540   int EmitEmbeddedConstantPool() {
1541     DCHECK(FLAG_enable_embedded_constant_pool);
1542     return constant_pool_builder_.Emit(this);
1543   }
1544 
ConstantPoolAccessIsInOverflow()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 
buffer_space()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.
StartBlockConstPool()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.
EndBlockConstPool()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 
is_const_pool_blocked()1603   bool is_const_pool_blocked() const {
1604     return (const_pool_blocked_nesting_ > 0) ||
1605            (pc_offset() < no_const_pool_before_);
1606   }
1607 
VfpRegisterIsAvailable(DwVfpRegister reg)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 
1708 class EnsureSpace BASE_EMBEDDED {
1709  public:
EnsureSpace(Assembler * assembler)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