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