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