v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
assembler-arm.h
Go to the documentation of this file.
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 #include <stdio.h>
43 #include "assembler.h"
44 #include "constants-arm.h"
45 #include "serialize.h"
46 
47 namespace v8 {
48 namespace internal {
49 
50 // CPU Registers.
51 //
52 // 1) We would prefer to use an enum, but enum values are assignment-
53 // compatible with int, which has caused code-generation bugs.
54 //
55 // 2) We would prefer to use a class instead of a struct but we don't like
56 // the register initialization to depend on the particular initialization
57 // order (which appears to be different on OS X, Linux, and Windows for the
58 // installed versions of C++ we tried). Using a struct permits C-style
59 // "initialization". Also, the Register objects cannot be const as this
60 // forces initialization stubs in MSVC, making us dependent on initialization
61 // order.
62 //
63 // 3) By not using an enum, we are possibly preventing the compiler from
64 // doing certain constant folds, which may significantly reduce the
65 // code generated for some assembly instructions (because they boil down
66 // to a few constants). If this is a problem, we could change the code
67 // such that we use an enum in optimized mode, and the struct in debug
68 // mode. This way we get the compile-time error checking in debug mode
69 // and best performance in optimized code.
70 
71 // Core register
72 struct Register {
73  static const int kNumRegisters = 16;
74  static const int kNumAllocatableRegisters = 8;
75  static const int kSizeInBytes = 4;
76 
77  static int ToAllocationIndex(Register reg) {
79  return reg.code();
80  }
81 
82  static Register FromAllocationIndex(int index) {
83  ASSERT(index >= 0 && index < kNumAllocatableRegisters);
84  return from_code(index);
85  }
86 
87  static const char* AllocationIndexToString(int index) {
88  ASSERT(index >= 0 && index < kNumAllocatableRegisters);
89  const char* const names[] = {
90  "r0",
91  "r1",
92  "r2",
93  "r3",
94  "r4",
95  "r5",
96  "r6",
97  "r7",
98  };
99  return names[index];
100  }
101 
102  static Register from_code(int code) {
103  Register r = { code };
104  return r;
105  }
106 
107  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
108  bool is(Register reg) const { return code_ == reg.code_; }
109  int code() const {
110  ASSERT(is_valid());
111  return code_;
112  }
113  int bit() const {
114  ASSERT(is_valid());
115  return 1 << code_;
116  }
117 
118  void set_code(int code) {
119  code_ = code;
120  ASSERT(is_valid());
121  }
122 
123  // Unfortunately we can't make this private in a struct.
124  int code_;
125 };
126 
127 // These constants are used in several locations, including static initializers
128 const int kRegister_no_reg_Code = -1;
129 const int kRegister_r0_Code = 0;
130 const int kRegister_r1_Code = 1;
131 const int kRegister_r2_Code = 2;
132 const int kRegister_r3_Code = 3;
133 const int kRegister_r4_Code = 4;
134 const int kRegister_r5_Code = 5;
135 const int kRegister_r6_Code = 6;
136 const int kRegister_r7_Code = 7;
137 const int kRegister_r8_Code = 8;
138 const int kRegister_r9_Code = 9;
139 const int kRegister_r10_Code = 10;
140 const int kRegister_fp_Code = 11;
141 const int kRegister_ip_Code = 12;
142 const int kRegister_sp_Code = 13;
143 const int kRegister_lr_Code = 14;
144 const int kRegister_pc_Code = 15;
145 
147 
156 // Used as context register.
158 // Used as lithium codegen scratch register.
160 // Used as roots register.
167 
168 
169 // Single word VFP register.
171  bool is_valid() const { return 0 <= code_ && code_ < 32; }
172  bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
173  int code() const {
174  ASSERT(is_valid());
175  return code_;
176  }
177  int bit() const {
178  ASSERT(is_valid());
179  return 1 << code_;
180  }
181  void split_code(int* vm, int* m) const {
182  ASSERT(is_valid());
183  *m = code_ & 0x1;
184  *vm = code_ >> 1;
185  }
186 
187  int code_;
188 };
189 
190 
191 // Double word VFP register.
193  static const int kNumRegisters = 16;
194  // A few double registers are reserved: one as a scratch register and one to
195  // hold 0.0, that does not fit in the immediate field of vmov instructions.
196  // d14: 0.0
197  // d15: scratch register.
198  static const int kNumReservedRegisters = 2;
201 
202  inline static int ToAllocationIndex(DwVfpRegister reg);
203 
204  static DwVfpRegister FromAllocationIndex(int index) {
205  ASSERT(index >= 0 && index < kNumAllocatableRegisters);
206  return from_code(index);
207  }
208 
209  static const char* AllocationIndexToString(int index) {
210  ASSERT(index >= 0 && index < kNumAllocatableRegisters);
211  const char* const names[] = {
212  "d0",
213  "d1",
214  "d2",
215  "d3",
216  "d4",
217  "d5",
218  "d6",
219  "d7",
220  "d8",
221  "d9",
222  "d10",
223  "d11",
224  "d12",
225  "d13"
226  };
227  return names[index];
228  }
229 
231  DwVfpRegister r = { code };
232  return r;
233  }
234 
235  // Supporting d0 to d15, can be later extended to d31.
236  bool is_valid() const { return 0 <= code_ && code_ < 16; }
237  bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
238  SwVfpRegister low() const {
239  SwVfpRegister reg;
240  reg.code_ = code_ * 2;
241 
242  ASSERT(reg.is_valid());
243  return reg;
244  }
245  SwVfpRegister high() const {
246  SwVfpRegister reg;
247  reg.code_ = (code_ * 2) + 1;
248 
249  ASSERT(reg.is_valid());
250  return reg;
251  }
252  int code() const {
253  ASSERT(is_valid());
254  return code_;
255  }
256  int bit() const {
257  ASSERT(is_valid());
258  return 1 << code_;
259  }
260  void split_code(int* vm, int* m) const {
261  ASSERT(is_valid());
262  *m = (code_ & 0x10) >> 4;
263  *vm = code_ & 0x0F;
264  }
265 
266  int code_;
267 };
268 
269 
271 
272 
273 // Support for the VFP registers s0 to s31 (d0 to d15).
274 // Note that "s(N):s(N+1)" is the same as "d(N/2)".
275 const SwVfpRegister s0 = { 0 };
276 const SwVfpRegister s1 = { 1 };
277 const SwVfpRegister s2 = { 2 };
278 const SwVfpRegister s3 = { 3 };
279 const SwVfpRegister s4 = { 4 };
280 const SwVfpRegister s5 = { 5 };
281 const SwVfpRegister s6 = { 6 };
282 const SwVfpRegister s7 = { 7 };
283 const SwVfpRegister s8 = { 8 };
284 const SwVfpRegister s9 = { 9 };
285 const SwVfpRegister s10 = { 10 };
286 const SwVfpRegister s11 = { 11 };
287 const SwVfpRegister s12 = { 12 };
288 const SwVfpRegister s13 = { 13 };
289 const SwVfpRegister s14 = { 14 };
290 const SwVfpRegister s15 = { 15 };
291 const SwVfpRegister s16 = { 16 };
292 const SwVfpRegister s17 = { 17 };
293 const SwVfpRegister s18 = { 18 };
294 const SwVfpRegister s19 = { 19 };
295 const SwVfpRegister s20 = { 20 };
296 const SwVfpRegister s21 = { 21 };
297 const SwVfpRegister s22 = { 22 };
298 const SwVfpRegister s23 = { 23 };
299 const SwVfpRegister s24 = { 24 };
300 const SwVfpRegister s25 = { 25 };
301 const SwVfpRegister s26 = { 26 };
302 const SwVfpRegister s27 = { 27 };
303 const SwVfpRegister s28 = { 28 };
304 const SwVfpRegister s29 = { 29 };
305 const SwVfpRegister s30 = { 30 };
306 const SwVfpRegister s31 = { 31 };
307 
308 const DwVfpRegister no_dreg = { -1 };
309 const DwVfpRegister d0 = { 0 };
310 const DwVfpRegister d1 = { 1 };
311 const DwVfpRegister d2 = { 2 };
312 const DwVfpRegister d3 = { 3 };
313 const DwVfpRegister d4 = { 4 };
314 const DwVfpRegister d5 = { 5 };
315 const DwVfpRegister d6 = { 6 };
316 const DwVfpRegister d7 = { 7 };
317 const DwVfpRegister d8 = { 8 };
318 const DwVfpRegister d9 = { 9 };
319 const DwVfpRegister d10 = { 10 };
320 const DwVfpRegister d11 = { 11 };
321 const DwVfpRegister d12 = { 12 };
322 const DwVfpRegister d13 = { 13 };
323 const DwVfpRegister d14 = { 14 };
324 const DwVfpRegister d15 = { 15 };
325 
326 // Aliases for double registers. Defined using #define instead of
327 // "static const DwVfpRegister&" because Clang complains otherwise when a
328 // compilation unit that includes this header doesn't use the variables.
329 #define kFirstCalleeSavedDoubleReg d8
330 #define kLastCalleeSavedDoubleReg d15
331 #define kDoubleRegZero d14
332 #define kScratchDoubleReg d15
333 
334 
335 // Coprocessor register
336 struct CRegister {
337  bool is_valid() const { return 0 <= code_ && code_ < 16; }
338  bool is(CRegister creg) const { return code_ == creg.code_; }
339  int code() const {
340  ASSERT(is_valid());
341  return code_;
342  }
343  int bit() const {
344  ASSERT(is_valid());
345  return 1 << code_;
346  }
347 
348  // Unfortunately we can't make this private in a struct.
349  int code_;
350 };
351 
352 
353 const CRegister no_creg = { -1 };
354 
355 const CRegister cr0 = { 0 };
356 const CRegister cr1 = { 1 };
357 const CRegister cr2 = { 2 };
358 const CRegister cr3 = { 3 };
359 const CRegister cr4 = { 4 };
360 const CRegister cr5 = { 5 };
361 const CRegister cr6 = { 6 };
362 const CRegister cr7 = { 7 };
363 const CRegister cr8 = { 8 };
364 const CRegister cr9 = { 9 };
365 const CRegister cr10 = { 10 };
366 const CRegister cr11 = { 11 };
367 const CRegister cr12 = { 12 };
368 const CRegister cr13 = { 13 };
369 const CRegister cr14 = { 14 };
370 const CRegister cr15 = { 15 };
371 
372 
373 // Coprocessor number
375  p0 = 0,
376  p1 = 1,
377  p2 = 2,
378  p3 = 3,
379  p4 = 4,
380  p5 = 5,
381  p6 = 6,
382  p7 = 7,
383  p8 = 8,
384  p9 = 9,
385  p10 = 10,
386  p11 = 11,
387  p12 = 12,
388  p13 = 13,
389  p14 = 14,
390  p15 = 15
391 };
392 
393 
394 // -----------------------------------------------------------------------------
395 // Machine instruction Operands
396 
397 // Class Operand represents a shifter operand in data processing instructions
398 class Operand BASE_EMBEDDED {
399  public:
400  // immediate
401  INLINE(explicit Operand(int32_t immediate,
402  RelocInfo::Mode rmode = RelocInfo::NONE));
403  INLINE(static Operand Zero()) {
404  return Operand(static_cast<int32_t>(0));
405  }
406  INLINE(explicit Operand(const ExternalReference& f));
407  explicit Operand(Handle<Object> handle);
408  INLINE(explicit Operand(Smi* value));
409 
410  // rm
411  INLINE(explicit Operand(Register rm));
412 
413  // rm <shift_op> shift_imm
414  explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
415 
416  // rm <shift_op> rs
417  explicit Operand(Register rm, ShiftOp shift_op, Register rs);
418 
419  // Return true if this is a register operand.
420  INLINE(bool is_reg() const);
421 
422  // Return true if this operand fits in one instruction so that no
423  // 2-instruction solution with a load into the ip register is necessary. If
424  // the instruction this operand is used for is a MOV or MVN instruction the
425  // actual instruction to use is required for this calculation. For other
426  // instructions instr is ignored.
427  bool is_single_instruction(Instr instr = 0) const;
428  bool must_use_constant_pool() const;
429 
430  inline int32_t immediate() const {
431  ASSERT(!rm_.is_valid());
432  return imm32_;
433  }
434 
435  Register rm() const { return rm_; }
436  Register rs() const { return rs_; }
437  ShiftOp shift_op() const { return shift_op_; }
438 
439  private:
440  Register rm_;
441  Register rs_;
442  ShiftOp shift_op_;
443  int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
444  int32_t imm32_; // valid if rm_ == no_reg
445  RelocInfo::Mode rmode_;
446 
447  friend class Assembler;
448 };
449 
450 
451 // Class MemOperand represents a memory operand in load and store instructions
453  public:
454  // [rn +/- offset] Offset/NegOffset
455  // [rn +/- offset]! PreIndex/NegPreIndex
456  // [rn], +/- offset PostIndex/NegPostIndex
457  // offset is any signed 32-bit value; offset is first loaded to register ip if
458  // it does not fit the addressing mode (12-bit unsigned and sign bit)
459  explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
460 
461  // [rn +/- rm] Offset/NegOffset
462  // [rn +/- rm]! PreIndex/NegPreIndex
463  // [rn], +/- rm PostIndex/NegPostIndex
464  explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
465 
466  // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
467  // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
468  // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
469  explicit MemOperand(Register rn, Register rm,
470  ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
471 
473  ASSERT(rm_.is(no_reg));
474  offset_ = offset;
475  }
476 
477  uint32_t offset() const {
478  ASSERT(rm_.is(no_reg));
479  return offset_;
480  }
481 
482  Register rn() const { return rn_; }
483  Register rm() const { return rm_; }
484  AddrMode am() const { return am_; }
485 
486  bool OffsetIsUint12Encodable() const {
487  return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
488  }
489 
490  private:
491  Register rn_; // base
492  Register rm_; // register offset
493  int32_t offset_; // valid if rm_ == no_reg
494  ShiftOp shift_op_;
495  int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
496  AddrMode am_; // bits P, U, and W
497 
498  friend class Assembler;
499 };
500 
501 // CpuFeatures keeps track of which features are supported by the target CPU.
502 // Supported features must be enabled by a Scope before use.
503 class CpuFeatures : public AllStatic {
504  public:
505  // Detect features of the target CPU. Set safe defaults if the serializer
506  // is enabled (snapshots must be portable).
507  static void Probe();
508 
509  // Check whether a feature is supported by the target CPU.
510  static bool IsSupported(CpuFeature f) {
511  ASSERT(initialized_);
512  if (f == VFP3 && !FLAG_enable_vfp3) return false;
513  return (supported_ & (1u << f)) != 0;
514  }
515 
516 #ifdef DEBUG
517  // Check whether a feature is currently enabled.
518  static bool IsEnabled(CpuFeature f) {
519  ASSERT(initialized_);
520  Isolate* isolate = Isolate::UncheckedCurrent();
521  if (isolate == NULL) {
522  // When no isolate is available, work as if we're running in
523  // release mode.
524  return IsSupported(f);
525  }
526  unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
527  return (enabled & (1u << f)) != 0;
528  }
529 #endif
530 
531  // Enable a specified feature within a scope.
533 #ifdef DEBUG
534 
535  public:
536  explicit Scope(CpuFeature f) {
537  unsigned mask = 1u << f;
540  (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
541  isolate_ = Isolate::UncheckedCurrent();
542  old_enabled_ = 0;
543  if (isolate_ != NULL) {
544  old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
545  isolate_->set_enabled_cpu_features(old_enabled_ | mask);
546  }
547  }
548  ~Scope() {
549  ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
550  if (isolate_ != NULL) {
551  isolate_->set_enabled_cpu_features(old_enabled_);
552  }
553  }
554 
555  private:
556  Isolate* isolate_;
557  unsigned old_enabled_;
558 #else
559 
560  public:
561  explicit Scope(CpuFeature f) {}
562 #endif
563  };
564 
565  class TryForceFeatureScope BASE_EMBEDDED {
566  public:
568  : old_supported_(CpuFeatures::supported_) {
569  if (CanForce()) {
570  CpuFeatures::supported_ |= (1u << f);
571  }
572  }
573 
575  if (CanForce()) {
576  CpuFeatures::supported_ = old_supported_;
577  }
578  }
579 
580  private:
581  static bool CanForce() {
582  // It's only safe to temporarily force support of CPU features
583  // when there's only a single isolate, which is guaranteed when
584  // the serializer is enabled.
585  return Serializer::enabled();
586  }
587 
588  const unsigned old_supported_;
589  };
590 
591  private:
592 #ifdef DEBUG
593  static bool initialized_;
594 #endif
595  static unsigned supported_;
596  static unsigned found_by_runtime_probing_;
597 
598  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
599 };
600 
601 
602 extern const Instr kMovLrPc;
603 extern const Instr kLdrPCMask;
604 extern const Instr kLdrPCPattern;
605 extern const Instr kBlxRegMask;
606 extern const Instr kBlxRegPattern;
607 extern const Instr kBlxIp;
608 
609 extern const Instr kMovMvnMask;
610 extern const Instr kMovMvnPattern;
611 extern const Instr kMovMvnFlip;
612 
613 extern const Instr kMovLeaveCCMask;
614 extern const Instr kMovLeaveCCPattern;
615 extern const Instr kMovwMask;
616 extern const Instr kMovwPattern;
617 extern const Instr kMovwLeaveCCFlip;
618 
619 extern const Instr kCmpCmnMask;
620 extern const Instr kCmpCmnPattern;
621 extern const Instr kCmpCmnFlip;
622 extern const Instr kAddSubFlip;
623 extern const Instr kAndBicFlip;
624 
625 
626 
627 class Assembler : public AssemblerBase {
628  public:
629  // Create an assembler. Instructions and relocation information are emitted
630  // into a buffer, with the instructions starting from the beginning and the
631  // relocation information starting from the end of the buffer. See CodeDesc
632  // for a detailed comment on the layout (globals.h).
633  //
634  // If the provided buffer is NULL, the assembler allocates and grows its own
635  // buffer, and buffer_size determines the initial buffer size. The buffer is
636  // owned by the assembler and deallocated upon destruction of the assembler.
637  //
638  // If the provided buffer is not NULL, the assembler uses the provided buffer
639  // for code generation and assumes its size to be buffer_size. If the buffer
640  // is too small, a fatal error occurs. No deallocation of the buffer is done
641  // upon destruction of the assembler.
642  Assembler(Isolate* isolate, void* buffer, int buffer_size);
643  ~Assembler();
644 
645  // Overrides the default provided by FLAG_debug_code.
646  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
647 
648  // GetCode emits any pending (non-emitted) code and fills the descriptor
649  // desc. GetCode() is idempotent; it returns the same result if no other
650  // Assembler functions are invoked in between GetCode() calls.
651  void GetCode(CodeDesc* desc);
652 
653  // Label operations & relative jumps (PPUM Appendix D)
654  //
655  // Takes a branch opcode (cc) and a label (L) and generates
656  // either a backward branch or a forward branch and links it
657  // to the label fixup chain. Usage:
658  //
659  // Label L; // unbound label
660  // j(cc, &L); // forward branch to unbound label
661  // bind(&L); // bind label to the current pc
662  // j(cc, &L); // backward branch to bound label
663  // bind(&L); // illegal: a label may be bound only once
664  //
665  // Note: The same Label can be used for forward and backward branches
666  // but it may be bound only once.
667 
668  void bind(Label* L); // binds an unbound label L to the current code position
669 
670  // Returns the branch offset to the given label from the current code position
671  // Links the label to the current position if it is still unbound
672  // Manages the jump elimination optimization if the second parameter is true.
673  int branch_offset(Label* L, bool jump_elimination_allowed);
674 
675  // Puts a labels target address at the given position.
676  // The high 8 bits are set to zero.
677  void label_at_put(Label* L, int at_offset);
678 
679  // Return the address in the constant pool of the code target address used by
680  // the branch/call instruction at pc.
681  INLINE(static Address target_address_address_at(Address pc));
682 
683  // Read/Modify the code target address in the branch/call instruction at pc.
685  INLINE(static void set_target_address_at(Address pc, Address target));
686 
687  // This sets the branch destination (which is in the constant pool on ARM).
688  // This is for calls and branches within generated code.
689  inline static void deserialization_set_special_target_at(
690  Address constant_pool_entry, Address target);
691 
692  // This sets the branch destination (which is in the constant pool on ARM).
693  // This is for calls and branches to runtime code.
694  inline static void set_external_target_at(Address constant_pool_entry,
695  Address target);
696 
697  // Here we are patching the address in the constant pool, not the actual call
698  // instruction. The address in the constant pool is the same size as a
699  // pointer.
700  static const int kSpecialTargetSize = kPointerSize;
701 
702  // Size of an instruction.
703  static const int kInstrSize = sizeof(Instr);
704 
705  // Distance between the instruction referring to the address of the call
706  // target and the return address.
707 #ifdef USE_BLX
708  // Call sequence is:
709  // ldr ip, [pc, #...] @ call address
710  // blx ip
711  // @ return address
712  static const int kCallTargetAddressOffset = 2 * kInstrSize;
713 #else
714  // Call sequence is:
715  // mov lr, pc
716  // ldr pc, [pc, #...] @ call address
717  // @ return address
718  static const int kCallTargetAddressOffset = kInstrSize;
719 #endif
720 
721  // Distance between start of patched return sequence and the emitted address
722  // to jump to.
723 #ifdef USE_BLX
724  // Patched return sequence is:
725  // ldr ip, [pc, #0] @ emited address and start
726  // blx ip
728 #else
729  // Patched return sequence is:
730  // mov lr, pc @ start of sequence
731  // ldr pc, [pc, #-4] @ emited address
733 #endif
734 
735  // Distance between start of patched debug break slot and the emitted address
736  // to jump to.
737 #ifdef USE_BLX
738  // Patched debug break slot code is:
739  // ldr ip, [pc, #0] @ emited address and start
740  // blx ip
742 #else
743  // Patched debug break slot code is:
744  // mov lr, pc @ start of sequence
745  // ldr pc, [pc, #-4] @ emited address
747 #endif
748 
749  // Difference between address of current opcode and value read from pc
750  // register.
751  static const int kPcLoadDelta = 8;
752 
753  static const int kJSReturnSequenceInstructions = 4;
754  static const int kDebugBreakSlotInstructions = 3;
755  static const int kDebugBreakSlotLength =
757 
758  // ---------------------------------------------------------------------------
759  // Code generation
760 
761  // Insert the smallest number of nop instructions
762  // possible to align the pc offset to a multiple
763  // of m. m must be a power of 2 (>= 4).
764  void Align(int m);
765  // Aligns code to something that's optimal for a jump target for the platform.
766  void CodeTargetAlign();
767 
768  // Branch instructions
769  void b(int branch_offset, Condition cond = al);
770  void bl(int branch_offset, Condition cond = al);
771  void blx(int branch_offset); // v5 and above
772  void blx(Register target, Condition cond = al); // v5 and above
773  void bx(Register target, Condition cond = al); // v5 and above, plus v4t
774 
775  // Convenience branch instructions using labels
776  void b(Label* L, Condition cond = al) {
777  b(branch_offset(L, cond == al), cond);
778  }
779  void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); }
780  void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); }
781  void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); }
782  void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
783 
784  // Data-processing instructions
785 
786  void and_(Register dst, Register src1, const Operand& src2,
787  SBit s = LeaveCC, Condition cond = al);
788 
789  void eor(Register dst, Register src1, const Operand& src2,
790  SBit s = LeaveCC, Condition cond = al);
791 
792  void sub(Register dst, Register src1, const Operand& src2,
793  SBit s = LeaveCC, Condition cond = al);
794  void sub(Register dst, Register src1, Register src2,
795  SBit s = LeaveCC, Condition cond = al) {
796  sub(dst, src1, Operand(src2), s, cond);
797  }
798 
799  void rsb(Register dst, Register src1, const Operand& src2,
800  SBit s = LeaveCC, Condition cond = al);
801 
802  void add(Register dst, Register src1, const Operand& src2,
803  SBit s = LeaveCC, Condition cond = al);
804  void add(Register dst, Register src1, Register src2,
805  SBit s = LeaveCC, Condition cond = al) {
806  add(dst, src1, Operand(src2), s, cond);
807  }
808 
809  void adc(Register dst, Register src1, const Operand& src2,
810  SBit s = LeaveCC, Condition cond = al);
811 
812  void sbc(Register dst, Register src1, const Operand& src2,
813  SBit s = LeaveCC, Condition cond = al);
814 
815  void rsc(Register dst, Register src1, const Operand& src2,
816  SBit s = LeaveCC, Condition cond = al);
817 
818  void tst(Register src1, const Operand& src2, Condition cond = al);
819  void tst(Register src1, Register src2, Condition cond = al) {
820  tst(src1, Operand(src2), cond);
821  }
822 
823  void teq(Register src1, const Operand& src2, Condition cond = al);
824 
825  void cmp(Register src1, const Operand& src2, Condition cond = al);
826  void cmp(Register src1, Register src2, Condition cond = al) {
827  cmp(src1, Operand(src2), cond);
828  }
829  void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
830 
831  void cmn(Register src1, const Operand& src2, Condition cond = al);
832 
833  void orr(Register dst, Register src1, const Operand& src2,
834  SBit s = LeaveCC, Condition cond = al);
835  void orr(Register dst, Register src1, Register src2,
836  SBit s = LeaveCC, Condition cond = al) {
837  orr(dst, src1, Operand(src2), s, cond);
838  }
839 
840  void mov(Register dst, const Operand& src,
841  SBit s = LeaveCC, Condition cond = al);
842  void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
843  mov(dst, Operand(src), s, cond);
844  }
845 
846  // ARMv7 instructions for loading a 32 bit immediate in two instructions.
847  // This may actually emit a different mov instruction, but on an ARMv7 it
848  // is guaranteed to only emit one instruction.
849  void movw(Register reg, uint32_t immediate, Condition cond = al);
850  // The constant for movt should be in the range 0-0xffff.
851  void movt(Register reg, uint32_t immediate, Condition cond = al);
852 
853  void bic(Register dst, Register src1, const Operand& src2,
854  SBit s = LeaveCC, Condition cond = al);
855 
856  void mvn(Register dst, const Operand& src,
857  SBit s = LeaveCC, Condition cond = al);
858 
859  // Multiply instructions
860 
861  void mla(Register dst, Register src1, Register src2, Register srcA,
862  SBit s = LeaveCC, Condition cond = al);
863 
864  void mul(Register dst, Register src1, Register src2,
865  SBit s = LeaveCC, Condition cond = al);
866 
867  void smlal(Register dstL, Register dstH, Register src1, Register src2,
868  SBit s = LeaveCC, Condition cond = al);
869 
870  void smull(Register dstL, Register dstH, Register src1, Register src2,
871  SBit s = LeaveCC, Condition cond = al);
872 
873  void umlal(Register dstL, Register dstH, Register src1, Register src2,
874  SBit s = LeaveCC, Condition cond = al);
875 
876  void umull(Register dstL, Register dstH, Register src1, Register src2,
877  SBit s = LeaveCC, Condition cond = al);
878 
879  // Miscellaneous arithmetic instructions
880 
881  void clz(Register dst, Register src, Condition cond = al); // v5 and above
882 
883  // Saturating instructions. v6 and above.
884 
885  // Unsigned saturate.
886  //
887  // Saturate an optionally shifted signed value to an unsigned range.
888  //
889  // usat dst, #satpos, src
890  // usat dst, #satpos, src, lsl #sh
891  // usat dst, #satpos, src, asr #sh
892  //
893  // Register dst will contain:
894  //
895  // 0, if s < 0
896  // (1 << satpos) - 1, if s > ((1 << satpos) - 1)
897  // s, otherwise
898  //
899  // where s is the contents of src after shifting (if used.)
900  void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
901 
902  // Bitfield manipulation instructions. v7 and above.
903 
904  void ubfx(Register dst, Register src, int lsb, int width,
905  Condition cond = al);
906 
907  void sbfx(Register dst, Register src, int lsb, int width,
908  Condition cond = al);
909 
910  void bfc(Register dst, int lsb, int width, Condition cond = al);
911 
912  void bfi(Register dst, Register src, int lsb, int width,
913  Condition cond = al);
914 
915  // Status register access instructions
916 
917  void mrs(Register dst, SRegister s, Condition cond = al);
918  void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
919 
920  // Load/Store instructions
921  void ldr(Register dst, const MemOperand& src, Condition cond = al);
922  void str(Register src, const MemOperand& dst, Condition cond = al);
923  void ldrb(Register dst, const MemOperand& src, Condition cond = al);
924  void strb(Register src, const MemOperand& dst, Condition cond = al);
925  void ldrh(Register dst, const MemOperand& src, Condition cond = al);
926  void strh(Register src, const MemOperand& dst, Condition cond = al);
927  void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
928  void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
929  void ldrd(Register dst1,
930  Register dst2,
931  const MemOperand& src, Condition cond = al);
932  void strd(Register src1,
933  Register src2,
934  const MemOperand& dst, Condition cond = al);
935 
936  // Load/Store multiple instructions
937  void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
938  void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
939 
940  // Exception-generating instructions and debugging support
941  void stop(const char* msg,
942  Condition cond = al,
943  int32_t code = kDefaultStopCode);
944 
945  void bkpt(uint32_t imm16); // v5 and above
946  void svc(uint32_t imm24, Condition cond = al);
947 
948  // Coprocessor instructions
949 
950  void cdp(Coprocessor coproc, int opcode_1,
951  CRegister crd, CRegister crn, CRegister crm,
952  int opcode_2, Condition cond = al);
953 
954  void cdp2(Coprocessor coproc, int opcode_1,
955  CRegister crd, CRegister crn, CRegister crm,
956  int opcode_2); // v5 and above
957 
958  void mcr(Coprocessor coproc, int opcode_1,
959  Register rd, CRegister crn, CRegister crm,
960  int opcode_2 = 0, Condition cond = al);
961 
962  void mcr2(Coprocessor coproc, int opcode_1,
963  Register rd, CRegister crn, CRegister crm,
964  int opcode_2 = 0); // v5 and above
965 
966  void mrc(Coprocessor coproc, int opcode_1,
967  Register rd, CRegister crn, CRegister crm,
968  int opcode_2 = 0, Condition cond = al);
969 
970  void mrc2(Coprocessor coproc, int opcode_1,
971  Register rd, CRegister crn, CRegister crm,
972  int opcode_2 = 0); // v5 and above
973 
974  void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
975  LFlag l = Short, Condition cond = al);
976  void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
977  LFlag l = Short, Condition cond = al);
978 
979  void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
980  LFlag l = Short); // v5 and above
981  void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
982  LFlag l = Short); // v5 and above
983 
984  // Support for VFP.
985  // All these APIs support S0 to S31 and D0 to D15.
986  // Currently these APIs do not support extended D registers, i.e, D16 to D31.
987  // However, some simple modifications can allow
988  // these APIs to support D16 to D31.
989 
990  void vldr(const DwVfpRegister dst,
991  const Register base,
992  int offset,
993  const Condition cond = al);
994  void vldr(const DwVfpRegister dst,
995  const MemOperand& src,
996  const Condition cond = al);
997 
998  void vldr(const SwVfpRegister dst,
999  const Register base,
1000  int offset,
1001  const Condition cond = al);
1002  void vldr(const SwVfpRegister dst,
1003  const MemOperand& src,
1004  const Condition cond = al);
1005 
1006  void vstr(const DwVfpRegister src,
1007  const Register base,
1008  int offset,
1009  const Condition cond = al);
1010  void vstr(const DwVfpRegister src,
1011  const MemOperand& dst,
1012  const Condition cond = al);
1013 
1014  void vstr(const SwVfpRegister src,
1015  const Register base,
1016  int offset,
1017  const Condition cond = al);
1018  void vstr(const SwVfpRegister src,
1019  const MemOperand& dst,
1020  const Condition cond = al);
1021 
1022  void vldm(BlockAddrMode am,
1023  Register base,
1024  DwVfpRegister first,
1025  DwVfpRegister last,
1026  Condition cond = al);
1027 
1028  void vstm(BlockAddrMode am,
1029  Register base,
1030  DwVfpRegister first,
1031  DwVfpRegister last,
1032  Condition cond = al);
1033 
1034  void vldm(BlockAddrMode am,
1035  Register base,
1036  SwVfpRegister first,
1037  SwVfpRegister last,
1038  Condition cond = al);
1039 
1040  void vstm(BlockAddrMode am,
1041  Register base,
1042  SwVfpRegister first,
1043  SwVfpRegister last,
1044  Condition cond = al);
1045 
1046  void vmov(const DwVfpRegister dst,
1047  double imm,
1048  const Condition cond = al);
1049  void vmov(const SwVfpRegister dst,
1050  const SwVfpRegister src,
1051  const Condition cond = al);
1052  void vmov(const DwVfpRegister dst,
1053  const DwVfpRegister src,
1054  const Condition cond = al);
1055  void vmov(const DwVfpRegister dst,
1056  const Register src1,
1057  const Register src2,
1058  const Condition cond = al);
1059  void vmov(const Register dst1,
1060  const Register dst2,
1061  const DwVfpRegister src,
1062  const Condition cond = al);
1063  void vmov(const SwVfpRegister dst,
1064  const Register src,
1065  const Condition cond = al);
1066  void vmov(const Register dst,
1067  const SwVfpRegister src,
1068  const Condition cond = al);
1069  void vcvt_f64_s32(const DwVfpRegister dst,
1070  const SwVfpRegister src,
1072  const Condition cond = al);
1073  void vcvt_f32_s32(const SwVfpRegister dst,
1074  const SwVfpRegister src,
1076  const Condition cond = al);
1077  void vcvt_f64_u32(const DwVfpRegister dst,
1078  const SwVfpRegister src,
1080  const Condition cond = al);
1081  void vcvt_s32_f64(const SwVfpRegister dst,
1082  const DwVfpRegister src,
1084  const Condition cond = al);
1085  void vcvt_u32_f64(const SwVfpRegister dst,
1086  const DwVfpRegister src,
1088  const Condition cond = al);
1089  void vcvt_f64_f32(const DwVfpRegister dst,
1090  const SwVfpRegister src,
1092  const Condition cond = al);
1093  void vcvt_f32_f64(const SwVfpRegister dst,
1094  const DwVfpRegister src,
1096  const Condition cond = al);
1097 
1098  void vneg(const DwVfpRegister dst,
1099  const DwVfpRegister src,
1100  const Condition cond = al);
1101  void vabs(const DwVfpRegister dst,
1102  const DwVfpRegister src,
1103  const Condition cond = al);
1104  void vadd(const DwVfpRegister dst,
1105  const DwVfpRegister src1,
1106  const DwVfpRegister src2,
1107  const Condition cond = al);
1108  void vsub(const DwVfpRegister dst,
1109  const DwVfpRegister src1,
1110  const DwVfpRegister src2,
1111  const Condition cond = al);
1112  void vmul(const DwVfpRegister dst,
1113  const DwVfpRegister src1,
1114  const DwVfpRegister src2,
1115  const Condition cond = al);
1116  void vdiv(const DwVfpRegister dst,
1117  const DwVfpRegister src1,
1118  const DwVfpRegister src2,
1119  const Condition cond = al);
1120  void vcmp(const DwVfpRegister src1,
1121  const DwVfpRegister src2,
1122  const Condition cond = al);
1123  void vcmp(const DwVfpRegister src1,
1124  const double src2,
1125  const Condition cond = al);
1126  void vmrs(const Register dst,
1127  const Condition cond = al);
1128  void vmsr(const Register dst,
1129  const Condition cond = al);
1130  void vsqrt(const DwVfpRegister dst,
1131  const DwVfpRegister src,
1132  const Condition cond = al);
1133 
1134  // Pseudo instructions
1135 
1136  // Different nop operations are used by the code generator to detect certain
1137  // states of the generated code.
1141  // IC markers.
1145  // Helper values.
1148  };
1149 
1150  void nop(int type = 0); // 0 is the default non-marking type.
1151 
1152  void push(Register src, Condition cond = al) {
1153  str(src, MemOperand(sp, 4, NegPreIndex), cond);
1154  }
1155 
1156  void pop(Register dst, Condition cond = al) {
1157  ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1158  }
1159 
1160  void pop() {
1161  add(sp, sp, Operand(kPointerSize));
1162  }
1163 
1164  // Jump unconditionally to given label.
1165  void jmp(Label* L) { b(L, al); }
1166 
1167  // Check the code size generated from label to here.
1168  int SizeOfCodeGeneratedSince(Label* label) {
1169  return pc_offset() - label->pos();
1170  }
1171 
1172  // Check the number of instructions generated from label to here.
1173  int InstructionsGeneratedSince(Label* label) {
1174  return SizeOfCodeGeneratedSince(label) / kInstrSize;
1175  }
1176 
1177  // Check whether an immediate fits an addressing mode 1 instruction.
1179 
1180  // Class for scoping postponing the constant pool generation.
1182  public:
1183  explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1184  assem_->StartBlockConstPool();
1185  }
1187  assem_->EndBlockConstPool();
1188  }
1189 
1190  private:
1191  Assembler* assem_;
1192 
1193  DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1194  };
1195 
1196  // Debugging
1197 
1198  // Mark address of the ExitJSFrame code.
1199  void RecordJSReturn();
1200 
1201  // Mark address of a debug break slot.
1202  void RecordDebugBreakSlot();
1203 
1204  // Record the AST id of the CallIC being compiled, so that it can be placed
1205  // in the relocation information.
1206  void SetRecordedAstId(unsigned ast_id) {
1208  recorded_ast_id_ = ast_id;
1209  }
1210 
1211  unsigned RecordedAstId() {
1213  return recorded_ast_id_;
1214  }
1215 
1217 
1218  // Record a comment relocation entry that can be used by a disassembler.
1219  // Use --code-comments to enable.
1220  void RecordComment(const char* msg);
1221 
1222  // Writes a single byte or word of data in the code stream. Used
1223  // for inline tables, e.g., jump-tables. The constant pool should be
1224  // emitted before any use of db and dd to ensure that constant pools
1225  // are not emitted as part of the tables generated.
1226  void db(uint8_t data);
1227  void dd(uint32_t data);
1228 
1229  int pc_offset() const { return pc_ - buffer_; }
1230 
1231  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1232 
1233  // Read/patch instructions
1234  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1235  void instr_at_put(int pos, Instr instr) {
1236  *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1237  }
1238  static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1239  static void instr_at_put(byte* pc, Instr instr) {
1240  *reinterpret_cast<Instr*>(pc) = instr;
1241  }
1242  static Condition GetCondition(Instr instr);
1243  static bool IsBranch(Instr instr);
1244  static int GetBranchOffset(Instr instr);
1245  static bool IsLdrRegisterImmediate(Instr instr);
1246  static int GetLdrRegisterImmediateOffset(Instr instr);
1247  static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
1248  static bool IsStrRegisterImmediate(Instr instr);
1249  static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1250  static bool IsAddRegisterImmediate(Instr instr);
1251  static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
1252  static Register GetRd(Instr instr);
1253  static Register GetRn(Instr instr);
1254  static Register GetRm(Instr instr);
1255  static bool IsPush(Instr instr);
1256  static bool IsPop(Instr instr);
1257  static bool IsStrRegFpOffset(Instr instr);
1258  static bool IsLdrRegFpOffset(Instr instr);
1259  static bool IsStrRegFpNegOffset(Instr instr);
1260  static bool IsLdrRegFpNegOffset(Instr instr);
1261  static bool IsLdrPcImmediateOffset(Instr instr);
1262  static bool IsTstImmediate(Instr instr);
1263  static bool IsCmpRegister(Instr instr);
1264  static bool IsCmpImmediate(Instr instr);
1265  static Register GetCmpImmediateRegister(Instr instr);
1266  static int GetCmpImmediateRawImmediate(Instr instr);
1267  static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1268 
1269  // Constants in pools are accessed via pc relative addressing, which can
1270  // reach +/-4KB thereby defining a maximum distance between the instruction
1271  // and the accessed constant.
1272  static const int kMaxDistToPool = 4*KB;
1274 
1275  // Postpone the generation of the constant pool for the specified number of
1276  // instructions.
1277  void BlockConstPoolFor(int instructions);
1278 
1279  // Check if is time to emit a constant pool.
1280  void CheckConstPool(bool force_emit, bool require_jump);
1281 
1282  protected:
1283  // Relocation for a type-recording IC has the AST id added to it. This
1284  // member variable is a way to pass the information from the call site to
1285  // the relocation info.
1287 
1288  bool emit_debug_code() const { return emit_debug_code_; }
1289 
1290  int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1291 
1292  // Decode branch instruction at pos and return branch target pos
1293  int target_at(int pos);
1294 
1295  // Patch branch instruction at pos to branch to given branch target pos
1296  void target_at_put(int pos, int target_pos);
1297 
1298  // Prevent contant pool emission until EndBlockConstPool is called.
1299  // Call to this function can be nested but must be followed by an equal
1300  // number of call to EndBlockConstpool.
1302  if (const_pool_blocked_nesting_++ == 0) {
1303  // Prevent constant pool checks happening by setting the next check to
1304  // the biggest possible offset.
1305  next_buffer_check_ = kMaxInt;
1306  }
1307  }
1308 
1309  // Resume constant pool emission. Need to be called as many time as
1310  // StartBlockConstPool to have an effect.
1312  if (--const_pool_blocked_nesting_ == 0) {
1313  // Check the constant pool hasn't been blocked for too long.
1314  ASSERT((num_pending_reloc_info_ == 0) ||
1315  (pc_offset() < (first_const_pool_use_ + kMaxDistToPool)));
1316  // Two cases:
1317  // * no_const_pool_before_ >= next_buffer_check_ and the emission is
1318  // still blocked
1319  // * no_const_pool_before_ < next_buffer_check_ and the next emit will
1320  // trigger a check.
1321  next_buffer_check_ = no_const_pool_before_;
1322  }
1323  }
1324 
1325  bool is_const_pool_blocked() const {
1326  return (const_pool_blocked_nesting_ > 0) ||
1327  (pc_offset() < no_const_pool_before_);
1328  }
1329 
1330  private:
1331  // Code buffer:
1332  // The buffer into which code and relocation info are generated.
1333  byte* buffer_;
1334  int buffer_size_;
1335  // True if the assembler owns the buffer, false if buffer is external.
1336  bool own_buffer_;
1337 
1338  int next_buffer_check_; // pc offset of next buffer check
1339 
1340  // Code generation
1341  // The relocation writer's position is at least kGap bytes below the end of
1342  // the generated instructions. This is so that multi-instruction sequences do
1343  // not have to check for overflow. The same is true for writes of large
1344  // relocation info entries.
1345  static const int kGap = 32;
1346  byte* pc_; // the program counter; moves forward
1347 
1348  // Constant pool generation
1349  // Pools are emitted in the instruction stream, preferably after unconditional
1350  // jumps or after returns from functions (in dead code locations).
1351  // If a long code sequence does not contain unconditional jumps, it is
1352  // necessary to emit the constant pool before the pool gets too far from the
1353  // location it is accessed from. In this case, we emit a jump over the emitted
1354  // constant pool.
1355  // Constants in the pool may be addresses of functions that gets relocated;
1356  // if so, a relocation info entry is associated to the constant pool entry.
1357 
1358  // Repeated checking whether the constant pool should be emitted is rather
1359  // expensive. By default we only check again once a number of instructions
1360  // has been generated. That also means that the sizing of the buffers is not
1361  // an exact science, and that we rely on some slop to not overrun buffers.
1362  static const int kCheckPoolIntervalInst = 32;
1363  static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
1364 
1365 
1366  // Average distance beetween a constant pool and the first instruction
1367  // accessing the constant pool. Longer distance should result in less I-cache
1368  // pollution.
1369  // In practice the distance will be smaller since constant pool emission is
1370  // forced after function return and sometimes after unconditional branches.
1371  static const int kAvgDistToPool = kMaxDistToPool - kCheckPoolInterval;
1372 
1373  // Emission of the constant pool may be blocked in some code sequences.
1374  int const_pool_blocked_nesting_; // Block emission if this is not zero.
1375  int no_const_pool_before_; // Block emission before this pc offset.
1376 
1377  // Keep track of the first instruction requiring a constant pool entry
1378  // since the previous constant pool was emitted.
1379  int first_const_pool_use_;
1380 
1381  // Relocation info generation
1382  // Each relocation is encoded as a variable size value
1383  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1384  RelocInfoWriter reloc_info_writer;
1385 
1386  // Relocation info records are also used during code generation as temporary
1387  // containers for constants and code target addresses until they are emitted
1388  // to the constant pool. These pending relocation info records are temporarily
1389  // stored in a separate buffer until a constant pool is emitted.
1390  // If every instruction in a long sequence is accessing the pool, we need one
1391  // pending relocation entry per instruction.
1392 
1393  // the buffer of pending relocation info
1394  RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo];
1395  // number of pending reloc info entries in the buffer
1396  int num_pending_reloc_info_;
1397 
1398  // The bound position, before this we cannot do instruction elimination.
1399  int last_bound_pos_;
1400 
1401  // Code emission
1402  inline void CheckBuffer();
1403  void GrowBuffer();
1404  inline void emit(Instr x);
1405 
1406  // Instruction generation
1407  void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1408  void addrmod2(Instr instr, Register rd, const MemOperand& x);
1409  void addrmod3(Instr instr, Register rd, const MemOperand& x);
1410  void addrmod4(Instr instr, Register rn, RegList rl);
1411  void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1412 
1413  // Labels
1414  void print(Label* L);
1415  void bind_to(Label* L, int pos);
1416  void link_to(Label* L, Label* appendix);
1417  void next(Label* L);
1418 
1419  // Record reloc info for current pc_
1420  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1421 
1423  friend class RelocInfo;
1424  friend class CodePatcher;
1425  friend class BlockConstPoolScope;
1426 
1427  PositionsRecorder positions_recorder_;
1428  bool emit_debug_code_;
1429  friend class PositionsRecorder;
1430  friend class EnsureSpace;
1431 };
1432 
1433 
1434 class EnsureSpace BASE_EMBEDDED {
1435  public:
1436  explicit EnsureSpace(Assembler* assembler) {
1437  assembler->CheckBuffer();
1438  }
1439 };
1440 
1441 
1442 } } // namespace v8::internal
1443 
1444 #endif // V8_ARM_ASSEMBLER_ARM_H_
byte * Address
Definition: globals.h:172
void cmp(Register src1, const Operand &src2, Condition cond=al)
static bool IsBranch(Instr instr)
const SwVfpRegister s2
void ldrsb(Register dst, const MemOperand &src, Condition cond=al)
const DwVfpRegister d11
const Instr kCmpCmnMask
bool ImmediateFitsAddrMode1Instruction(int32_t imm32)
const SwVfpRegister s28
static const int kNumRegisters
void vcvt_f64_u32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
void mrc(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0, Condition cond=al)
int InstructionsGeneratedSince(Label *label)
static int GetBranchOffset(Instr instr)
const Instr kMovwMask
const SwVfpRegister s12
const SwVfpRegister s29
static const int kDebugBreakSlotInstructions
void db(uint8_t data)
void vcvt_f32_f64(const SwVfpRegister dst, const DwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
const SwVfpRegister s25
const SwVfpRegister s26
const CRegister cr10
const Instr kLdrPCMask
int32_t offset() const
const SwVfpRegister s17
static bool IsCmpRegister(Instr instr)
const Register r3
const Instr kMovwLeaveCCFlip
void strh(Register src, const MemOperand &dst, Condition cond=al)
void bic(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void mrs(Register dst, SRegister s, Condition cond=al)
const Instr kLdrPCPattern
const Instr kMovMvnPattern
static void deserialization_set_special_target_at(Address constant_pool_entry, Address target)
static bool IsStrRegFpNegOffset(Instr instr)
void instr_at_put(int pos, Instr instr)
const SwVfpRegister s7
void vabs(const DwVfpRegister dst, const DwVfpRegister src, const Condition cond=al)
void set_code(int code)
const SwVfpRegister s8
const SwVfpRegister s10
const int kRegister_r7_Code
const DwVfpRegister d8
void sbc(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
const Instr kMovLrPc
static bool IsStrRegisterImmediate(Instr instr)
const int KB
Definition: globals.h:221
void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond=al)
void pop(Register dst, Condition cond=al)
void mla(Register dst, Register src1, Register src2, Register srcA, SBit s=LeaveCC, Condition cond=al)
const DwVfpRegister d5
const int kRegister_pc_Code
const DwVfpRegister d0
int SizeOfCodeGeneratedSince(Label *label)
const SwVfpRegister s16
void bfi(Register dst, Register src, int lsb, int width, Condition cond=al)
const Register r6
static int GetCmpImmediateRawImmediate(Instr instr)
int32_t immediate() const
void dd(uint32_t data)
void push(Register src, Condition cond=al)
void tst(Register src1, Register src2, Condition cond=al)
void b(int branch_offset, Condition cond=al)
int int32_t
Definition: unicode.cc:47
void cmn(Register src1, const Operand &src2, Condition cond=al)
uint32_t RegList
Definition: frames.h:38
void ldrb(Register dst, const MemOperand &src, Condition cond=al)
const Instr kAddSubFlip
void smull(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
SwVfpRegister high() const
static const int kNumAllocatableRegisters
static bool IsSupported(CpuFeature f)
void clz(Register dst, Register src, Condition cond=al)
INLINE(static Address target_address_address_at(Address pc))
const int kMaxInt
Definition: globals.h:224
static bool enabled()
Definition: serialize.h:480
void vmul(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
const SwVfpRegister s14
const SwVfpRegister s21
const DwVfpRegister d12
static bool IsStrRegFpOffset(Instr instr)
void vsqrt(const DwVfpRegister dst, const DwVfpRegister src, const Condition cond=al)
static Register GetRm(Instr instr)
void bl(Label *L, Condition cond=al)
const DwVfpRegister d6
#define ASSERT(condition)
Definition: checks.h:270
static const int kPatchReturnSequenceAddressOffset
void bl(Condition cond, Label *L)
void svc(uint32_t imm24, Condition cond=al)
static bool IsCmpImmediate(Instr instr)
void stm(BlockAddrMode am, Register base, RegList src, Condition cond=al)
static Instr instr_at(byte *pc)
const Instr kBlxRegMask
void ldrd(Register dst1, Register dst2, const MemOperand &src, Condition cond=al)
void ldc2(Coprocessor coproc, CRegister crd, const MemOperand &src, LFlag l=Short)
static void instr_at_put(byte *pc, Instr instr)
const Register r2
static DwVfpRegister from_code(int code)
const Instr kCmpCmnPattern
void blx(int branch_offset)
void target_at_put(int pos, int target_pos)
void vdiv(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
const DwVfpRegister d9
const SwVfpRegister s23
const int kRegister_r3_Code
void vcvt_s32_f64(const SwVfpRegister dst, const DwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
bool is(SwVfpRegister reg) const
static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset)
void strb(Register src, const MemOperand &dst, Condition cond=al)
bool is_uint12(int x)
Definition: assembler.h:846
const SwVfpRegister s22
void ldrh(Register dst, const MemOperand &src, Condition cond=al)
void BlockConstPoolFor(int instructions)
static const char * AllocationIndexToString(int index)
const SwVfpRegister s6
bool is(CRegister creg) const
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 instructions(ARM only)") DEFINE_bool(enable_armv7
static const int kNumRegisters
Definition: assembler-arm.h:73
const CRegister cr12
EnsureSpace(Assembler *assembler)
void mvn(Register dst, const Operand &src, SBit s=LeaveCC, Condition cond=al)
static Condition GetCondition(Instr instr)
static DwVfpRegister FromAllocationIndex(int index)
const SwVfpRegister s31
uint8_t byte
Definition: globals.h:171
const CRegister cr8
void vneg(const DwVfpRegister dst, const DwVfpRegister src, const Condition cond=al)
const SwVfpRegister s18
void vcvt_f64_s32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
const int kRegister_r2_Code
const unsigned kNoASTId
Definition: assembler.h:54
static bool IsPush(Instr instr)
void vmov(const DwVfpRegister dst, double imm, const Condition cond=al)
void vldm(BlockAddrMode am, Register base, DwVfpRegister first, DwVfpRegister last, Condition cond=al)
const Register sp
const SwVfpRegister s3
bool OffsetIsUint12Encodable() const
DwVfpRegister DoubleRegister
const DwVfpRegister d13
const int32_t kDefaultStopCode
void vsub(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
static const int kSpecialTargetSize
const SwVfpRegister s13
const int kRegister_r5_Code
const Register ip
void GetCode(CodeDesc *desc)
const Register r9
const int kPointerSize
Definition: globals.h:234
void strd(Register src1, Register src2, const MemOperand &dst, Condition cond=al)
void orr(Register dst, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
const SwVfpRegister s27
static const int kPcLoadDelta
void teq(Register src1, const Operand &src2, Condition cond=al)
const Instr kAndBicFlip
int branch_offset(Label *L, bool jump_elimination_allowed)
const DwVfpRegister d7
static void set_target_address_at(Address pc, Address target)
const int kRegister_r4_Code
void umlal(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
static bool IsPop(Instr instr)
const Instr kMovLeaveCCMask
void movt(Register reg, uint32_t immediate, Condition cond=al)
const CRegister cr11
void cdp2(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn, CRegister crm, int opcode_2)
static void set_external_target_at(Address constant_pool_entry, Address target)
const Instr kBlxIp
static Register FromAllocationIndex(int index)
Definition: assembler-arm.h:82
void vadd(const DwVfpRegister dst, const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
const Register pc
static Register from_code(int code)
void set_emit_debug_code(bool value)
const int kRegister_r8_Code
void vmrs(const Register dst, const Condition cond=al)
static int ToAllocationIndex(Register reg)
Definition: assembler-arm.h:77
void str(Register src, const MemOperand &dst, Condition cond=al)
const SwVfpRegister s0
void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond=al)
const DwVfpRegister d3
const int kRegister_fp_Code
void split_code(int *vm, int *m) const
void CheckConstPool(bool force_emit, bool require_jump)
void mrc2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0)
const int kRegister_lr_Code
const DwVfpRegister no_dreg
const Register r0
static Register GetRn(Instr instr)
void mov(Register dst, Register src, SBit s=LeaveCC, Condition cond=al)
const SwVfpRegister s19
static const int kCallTargetAddressOffset
#define BASE_EMBEDDED
Definition: allocation.h:68
void eor(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
const SwVfpRegister s5
void add(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
static Instr SetStrRegisterImmediateOffset(Instr instr, int offset)
void set_offset(int32_t offset)
static const int kDebugBreakSlotLength
static bool IsTstImmediate(Instr instr)
void vcvt_f64_f32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
static Register GetRd(Instr instr)
static bool IsNop(Instr instr, int type=NON_MARKING_NOP)
static const int kMaxNumPendingRelocInfo
const int kRegister_r10_Code
void vcvt_u32_f64(const SwVfpRegister dst, const DwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
const SwVfpRegister s1
void ldr(Register dst, const MemOperand &src, Condition cond=al)
void stop(const char *msg, Condition cond=al, int32_t code=kDefaultStopCode)
const CRegister cr6
const CRegister cr15
const Register lr
void b(Condition cond, Label *L)
void movw(Register reg, uint32_t immediate, Condition cond=al)
void sub(Register dst, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
bool is_valid() const
bool is(Register reg) const
static Address target_address_at(Address pc)
static Instr SetAddRegisterImmediateOffset(Instr instr, int offset)
const Instr kMovLeaveCCPattern
const CRegister cr7
const Register r1
const DwVfpRegister d14
void smlal(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
const int kRegister_r6_Code
void vldr(const DwVfpRegister dst, const Register base, int offset, const Condition cond=al)
const CRegister cr2
void RecordComment(const char *msg)
const CRegister cr14
void bl(int branch_offset, Condition cond=al)
INLINE(static HeapObject *EnsureDoubleAligned(Heap *heap, HeapObject *object, int size))
static int ToAllocationIndex(DwVfpRegister reg)
void rsb(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
static Register GetCmpImmediateRegister(Instr instr)
void sbfx(Register dst, Register src, int lsb, int width, Condition cond=al)
const Instr kBlxRegPattern
uint32_t offset() const
const SwVfpRegister s30
const Instr kMovMvnMask
bool is_const_pool_blocked() const
friend class PositionsRecorder
INLINE(static Operand Zero())
static bool IsAddRegisterImmediate(Instr instr)
void vcmp(const DwVfpRegister src1, const DwVfpRegister src2, const Condition cond=al)
void mov(Register dst, const Operand &src, SBit s=LeaveCC, Condition cond=al)
const Register r8
static const int kNumAllocatableRegisters
Definition: assembler-arm.h:74
const CRegister cr13
void vmsr(const Register dst, const Condition cond=al)
void vstr(const DwVfpRegister src, const Register base, int offset, const Condition cond=al)
void SetRecordedAstId(unsigned ast_id)
Assembler(Isolate *isolate, void *buffer, int buffer_size)
void usat(Register dst, int satpos, const Operand &src, Condition cond=al)
void ubfx(Register dst, Register src, int lsb, int width, Condition cond=al)
const Instr kMovwPattern
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
void bx(Register target, Condition cond=al)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
void ldrsh(Register dst, const MemOperand &src, Condition cond=al)
SwVfpRegister low() const
static const int kJSReturnSequenceInstructions
const SwVfpRegister s4
uint32_t SRegisterFieldMask
const CRegister no_creg
void orr(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
const DwVfpRegister d2
const SwVfpRegister s20
bool is(DwVfpRegister reg) const
PositionsRecorder * positions_recorder()
const int kRegister_r0_Code
static const int kInstrSize
void cdp(Coprocessor coproc, int opcode_1, CRegister crd, CRegister crn, CRegister crm, int opcode_2, Condition cond=al)
MemOperand(Register rn, int32_t offset=0)
static const char * AllocationIndexToString(int index)
Definition: assembler-arm.h:87
static const int kSizeInBytes
Definition: assembler-arm.h:75
const int kRegister_r1_Code
const CRegister cr3
const SwVfpRegister s9
void cmp(Register src1, Register src2, Condition cond=al)
const Register r10
const Instr kMovMvnFlip
void bfc(Register dst, int lsb, int width, Condition cond=al)
const Register no_reg
const DwVfpRegister d1
void and_(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void label_at_put(Label *L, int at_offset)
const CRegister cr0
const CRegister cr5
const Register fp
const CRegister cr9
const DwVfpRegister d10
const int kRegister_r9_Code
const int kRegister_ip_Code
const int kRegister_sp_Code
void umull(Register dstL, Register dstH, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
const CRegister cr1
static bool IsLdrRegisterImmediate(Instr instr)
void msr(SRegisterFieldMask fields, const Operand &src, Condition cond=al)
const SwVfpRegister s11
void ldc(Coprocessor coproc, CRegister crd, const MemOperand &src, LFlag l=Short, Condition cond=al)
const CRegister cr4
const SwVfpRegister s15
static bool IsLdrRegFpNegOffset(Instr instr)
void bkpt(uint32_t imm16)
static const int kPatchDebugBreakSlotAddressOffset
void vstm(BlockAddrMode am, Register base, DwVfpRegister first, DwVfpRegister last, Condition cond=al)
static int GetLdrRegisterImmediateOffset(Instr instr)
void b(Label *L, Condition cond=al)
void sub(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
bool emit_debug_code() const
void vcvt_f32_s32(const SwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
void rsc(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void tst(Register src1, const Operand &src2, Condition cond=al)
FlagType type() const
Definition: flags.cc:1358
static bool IsLdrRegFpOffset(Instr instr)
void add(Register dst, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
const Register r5
const int kRegister_no_reg_Code
const DwVfpRegister d15
const DwVfpRegister d4
const Instr kCmpCmnFlip
static const int kNumReservedRegisters
void mcr2(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0)
void mul(Register dst, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
static bool IsLdrPcImmediateOffset(Instr instr)
void mcr(Coprocessor coproc, int opcode_1, Register rd, CRegister crn, CRegister crm, int opcode_2=0, Condition cond=al)
const SwVfpRegister s24
void split_code(int *vm, int *m) const
static const int kMaxDistToPool
const Register r4
void adc(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
const Register r7