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