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