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
47namespace v8 {
48namespace 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
72struct 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) {
78    ASSERT(reg.code() < kNumAllocatableRegisters);
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
128const int kRegister_no_reg_Code = -1;
129const int kRegister_r0_Code = 0;
130const int kRegister_r1_Code = 1;
131const int kRegister_r2_Code = 2;
132const int kRegister_r3_Code = 3;
133const int kRegister_r4_Code = 4;
134const int kRegister_r5_Code = 5;
135const int kRegister_r6_Code = 6;
136const int kRegister_r7_Code = 7;
137const int kRegister_r8_Code = 8;
138const int kRegister_r9_Code = 9;
139const int kRegister_r10_Code = 10;
140const int kRegister_fp_Code = 11;
141const int kRegister_ip_Code = 12;
142const int kRegister_sp_Code = 13;
143const int kRegister_lr_Code = 14;
144const int kRegister_pc_Code = 15;
145
146const Register no_reg = { kRegister_no_reg_Code };
147
148const Register r0  = { kRegister_r0_Code };
149const Register r1  = { kRegister_r1_Code };
150const Register r2  = { kRegister_r2_Code };
151const Register r3  = { kRegister_r3_Code };
152const Register r4  = { kRegister_r4_Code };
153const Register r5  = { kRegister_r5_Code };
154const Register r6  = { kRegister_r6_Code };
155const Register r7  = { kRegister_r7_Code };
156// Used as context register.
157const Register r8  = { kRegister_r8_Code };
158// Used as lithium codegen scratch register.
159const Register r9  = { kRegister_r9_Code };
160// Used as roots register.
161const Register r10 = { kRegister_r10_Code };
162const Register fp  = { kRegister_fp_Code };
163const Register ip  = { kRegister_ip_Code };
164const Register sp  = { kRegister_sp_Code };
165const Register lr  = { kRegister_lr_Code };
166const Register pc  = { kRegister_pc_Code };
167
168
169// Single word VFP register.
170struct SwVfpRegister {
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.
192struct DwVfpRegister {
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;
199  static const int kNumAllocatableRegisters = kNumRegisters -
200      kNumReservedRegisters;
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
230  static DwVfpRegister from_code(int code) {
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
270typedef DwVfpRegister DoubleRegister;
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)".
275const SwVfpRegister s0  = {  0 };
276const SwVfpRegister s1  = {  1 };
277const SwVfpRegister s2  = {  2 };
278const SwVfpRegister s3  = {  3 };
279const SwVfpRegister s4  = {  4 };
280const SwVfpRegister s5  = {  5 };
281const SwVfpRegister s6  = {  6 };
282const SwVfpRegister s7  = {  7 };
283const SwVfpRegister s8  = {  8 };
284const SwVfpRegister s9  = {  9 };
285const SwVfpRegister s10 = { 10 };
286const SwVfpRegister s11 = { 11 };
287const SwVfpRegister s12 = { 12 };
288const SwVfpRegister s13 = { 13 };
289const SwVfpRegister s14 = { 14 };
290const SwVfpRegister s15 = { 15 };
291const SwVfpRegister s16 = { 16 };
292const SwVfpRegister s17 = { 17 };
293const SwVfpRegister s18 = { 18 };
294const SwVfpRegister s19 = { 19 };
295const SwVfpRegister s20 = { 20 };
296const SwVfpRegister s21 = { 21 };
297const SwVfpRegister s22 = { 22 };
298const SwVfpRegister s23 = { 23 };
299const SwVfpRegister s24 = { 24 };
300const SwVfpRegister s25 = { 25 };
301const SwVfpRegister s26 = { 26 };
302const SwVfpRegister s27 = { 27 };
303const SwVfpRegister s28 = { 28 };
304const SwVfpRegister s29 = { 29 };
305const SwVfpRegister s30 = { 30 };
306const SwVfpRegister s31 = { 31 };
307
308const DwVfpRegister no_dreg = { -1 };
309const DwVfpRegister d0  = {  0 };
310const DwVfpRegister d1  = {  1 };
311const DwVfpRegister d2  = {  2 };
312const DwVfpRegister d3  = {  3 };
313const DwVfpRegister d4  = {  4 };
314const DwVfpRegister d5  = {  5 };
315const DwVfpRegister d6  = {  6 };
316const DwVfpRegister d7  = {  7 };
317const DwVfpRegister d8  = {  8 };
318const DwVfpRegister d9  = {  9 };
319const DwVfpRegister d10 = { 10 };
320const DwVfpRegister d11 = { 11 };
321const DwVfpRegister d12 = { 12 };
322const DwVfpRegister d13 = { 13 };
323const DwVfpRegister d14 = { 14 };
324const 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
336struct 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
353const CRegister no_creg = { -1 };
354
355const CRegister cr0  = {  0 };
356const CRegister cr1  = {  1 };
357const CRegister cr2  = {  2 };
358const CRegister cr3  = {  3 };
359const CRegister cr4  = {  4 };
360const CRegister cr5  = {  5 };
361const CRegister cr6  = {  6 };
362const CRegister cr7  = {  7 };
363const CRegister cr8  = {  8 };
364const CRegister cr9  = {  9 };
365const CRegister cr10 = { 10 };
366const CRegister cr11 = { 11 };
367const CRegister cr12 = { 12 };
368const CRegister cr13 = { 13 };
369const CRegister cr14 = { 14 };
370const CRegister cr15 = { 15 };
371
372
373// Coprocessor number
374enum Coprocessor {
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
398class 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
452class MemOperand BASE_EMBEDDED {
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
472  void set_offset(int32_t offset) {
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.
503class 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.
532  class Scope BASE_EMBEDDED {
533#ifdef DEBUG
534
535   public:
536    explicit Scope(CpuFeature f) {
537      unsigned mask = 1u << f;
538      ASSERT(CpuFeatures::IsSupported(f));
539      ASSERT(!Serializer::enabled() ||
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:
567    explicit TryForceFeatureScope(CpuFeature f)
568        : old_supported_(CpuFeatures::supported_) {
569      if (CanForce()) {
570        CpuFeatures::supported_ |= (1u << f);
571      }
572    }
573
574    ~TryForceFeatureScope() {
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
602extern const Instr kMovLrPc;
603extern const Instr kLdrPCMask;
604extern const Instr kLdrPCPattern;
605extern const Instr kBlxRegMask;
606extern const Instr kBlxRegPattern;
607extern const Instr kBlxIp;
608
609extern const Instr kMovMvnMask;
610extern const Instr kMovMvnPattern;
611extern const Instr kMovMvnFlip;
612
613extern const Instr kMovLeaveCCMask;
614extern const Instr kMovLeaveCCPattern;
615extern const Instr kMovwMask;
616extern const Instr kMovwPattern;
617extern const Instr kMovwLeaveCCFlip;
618
619extern const Instr kCmpCmnMask;
620extern const Instr kCmpCmnPattern;
621extern const Instr kCmpCmnFlip;
622extern const Instr kAddSubFlip;
623extern const Instr kAndBicFlip;
624
625
626
627class 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.
684  INLINE(static Address target_address_at(Address 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
727  static const int kPatchReturnSequenceAddressOffset =  0 * kInstrSize;
728#else
729  // Patched return sequence is:
730  //  mov  lr, pc         @ start of sequence
731  //  ldr  pc, [pc, #-4]  @ emited address
732  static const int kPatchReturnSequenceAddressOffset =  kInstrSize;
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
741  static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
742#else
743  // Patched debug break slot code is:
744  //  mov  lr, pc         @ start of sequence
745  //  ldr  pc, [pc, #-4]  @ emited address
746  static const int kPatchDebugBreakSlotAddressOffset =  kInstrSize;
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 =
756      kDebugBreakSlotInstructions * kInstrSize;
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,
1071                    VFPConversionMode mode = kDefaultRoundToZero,
1072                    const Condition cond = al);
1073  void vcvt_f32_s32(const SwVfpRegister dst,
1074                    const SwVfpRegister src,
1075                    VFPConversionMode mode = kDefaultRoundToZero,
1076                    const Condition cond = al);
1077  void vcvt_f64_u32(const DwVfpRegister dst,
1078                    const SwVfpRegister src,
1079                    VFPConversionMode mode = kDefaultRoundToZero,
1080                    const Condition cond = al);
1081  void vcvt_s32_f64(const SwVfpRegister dst,
1082                    const DwVfpRegister src,
1083                    VFPConversionMode mode = kDefaultRoundToZero,
1084                    const Condition cond = al);
1085  void vcvt_u32_f64(const SwVfpRegister dst,
1086                    const DwVfpRegister src,
1087                    VFPConversionMode mode = kDefaultRoundToZero,
1088                    const Condition cond = al);
1089  void vcvt_f64_f32(const DwVfpRegister dst,
1090                    const SwVfpRegister src,
1091                    VFPConversionMode mode = kDefaultRoundToZero,
1092                    const Condition cond = al);
1093  void vcvt_f32_f64(const SwVfpRegister dst,
1094                    const DwVfpRegister src,
1095                    VFPConversionMode mode = kDefaultRoundToZero,
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.
1138  enum NopMarkerTypes {
1139    NON_MARKING_NOP = 0,
1140    DEBUG_BREAK_NOP,
1141    // IC markers.
1142    PROPERTY_ACCESS_INLINED,
1143    PROPERTY_ACCESS_INLINED_CONTEXT,
1144    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1145    // Helper values.
1146    LAST_CODE_MARKER,
1147    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
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.
1178  bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1179
1180  // Class for scoping postponing the constant pool generation.
1181  class BlockConstPoolScope {
1182   public:
1183    explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1184      assem_->StartBlockConstPool();
1185    }
1186    ~BlockConstPoolScope() {
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) {
1207    ASSERT(recorded_ast_id_ == kNoASTId);
1208    recorded_ast_id_ = ast_id;
1209  }
1210
1211  unsigned RecordedAstId() {
1212    ASSERT(recorded_ast_id_ != kNoASTId);
1213    return recorded_ast_id_;
1214  }
1215
1216  void ClearRecordedAstId() { recorded_ast_id_ = kNoASTId; }
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;
1273  static const int kMaxNumPendingRelocInfo = kMaxDistToPool/kInstrSize;
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.
1286  unsigned recorded_ast_id_;
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.
1301  void StartBlockConstPool() {
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.
1311  void EndBlockConstPool() {
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
1422  friend class RegExpMacroAssemblerARM;
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
1434class 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_
1445