1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions
8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
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
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.
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.
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.
37 // A light-weight ARM Assembler
38 // Generates user mode instructions for the ARM architecture up to version 5
40 #ifndef V8_ARM_ASSEMBLER_ARM_H_
41 #define V8_ARM_ASSEMBLER_ARM_H_
46 #include "src/arm/constants-arm.h"
47 #include "src/assembler.h"
48 #include "src/compiler.h"
55 // 1) We would prefer to use an enum, but enum values are assignment-
56 // compatible with int, which has caused code-generation bugs.
58 // 2) We would prefer to use a class instead of a struct but we don't like
59 // the register initialization to depend on the particular initialization
60 // order (which appears to be different on OS X, Linux, and Windows for the
61 // installed versions of C++ we tried). Using a struct permits C-style
62 // "initialization". Also, the Register objects cannot be const as this
63 // forces initialization stubs in MSVC, making us dependent on initialization
66 // 3) By not using an enum, we are possibly preventing the compiler from
67 // doing certain constant folds, which may significantly reduce the
68 // code generated for some assembly instructions (because they boil down
69 // to a few constants). If this is a problem, we could change the code
70 // such that we use an enum in optimized mode, and the struct in debug
71 // mode. This way we get the compile-time error checking in debug mode
72 // and best performance in optimized code.
74 // These constants are used in several locations, including static initializers
75 const int kRegister_no_reg_Code = -1;
76 const int kRegister_r0_Code = 0;
77 const int kRegister_r1_Code = 1;
78 const int kRegister_r2_Code = 2;
79 const int kRegister_r3_Code = 3;
80 const int kRegister_r4_Code = 4;
81 const int kRegister_r5_Code = 5;
82 const int kRegister_r6_Code = 6;
83 const int kRegister_r7_Code = 7;
84 const int kRegister_r8_Code = 8;
85 const int kRegister_r9_Code = 9;
86 const int kRegister_r10_Code = 10;
87 const int kRegister_fp_Code = 11;
88 const int kRegister_ip_Code = 12;
89 const int kRegister_sp_Code = 13;
90 const int kRegister_lr_Code = 14;
91 const int kRegister_pc_Code = 15;
95 static const int kNumRegisters = 16;
96 static const int kMaxNumAllocatableRegisters =
97 FLAG_enable_ool_constant_pool ? 8 : 9;
98 static const int kSizeInBytes = 4;
100 inline static int NumAllocatableRegisters();
102 static int ToAllocationIndex(Register reg) {
103 DCHECK(reg.code() < kMaxNumAllocatableRegisters);
107 static Register FromAllocationIndex(int index) {
108 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
109 return from_code(index);
112 static const char* AllocationIndexToString(int index) {
113 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
114 const char* const names[] = {
125 if (FLAG_enable_ool_constant_pool && (index >= 7)) {
126 return names[index + 1];
131 static Register from_code(int code) {
132 Register r = { code };
136 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
137 bool is(Register reg) const { return code_ == reg.code_; }
147 void set_code(int code) {
152 // Unfortunately we can't make this private in a struct.
156 const Register no_reg = { kRegister_no_reg_Code };
158 const Register r0 = { kRegister_r0_Code };
159 const Register r1 = { kRegister_r1_Code };
160 const Register r2 = { kRegister_r2_Code };
161 const Register r3 = { kRegister_r3_Code };
162 const Register r4 = { kRegister_r4_Code };
163 const Register r5 = { kRegister_r5_Code };
164 const Register r6 = { kRegister_r6_Code };
165 // Used as constant pool pointer register if FLAG_enable_ool_constant_pool.
166 const Register r7 = { kRegister_r7_Code };
167 // Used as context register.
168 const Register r8 = { kRegister_r8_Code };
169 // Used as lithium codegen scratch register.
170 const Register r9 = { kRegister_r9_Code };
171 // Used as roots register.
172 const Register r10 = { kRegister_r10_Code };
173 const Register fp = { kRegister_fp_Code };
174 const Register ip = { kRegister_ip_Code };
175 const Register sp = { kRegister_sp_Code };
176 const Register lr = { kRegister_lr_Code };
177 const Register pc = { kRegister_pc_Code };
179 // Single word VFP register.
180 struct SwVfpRegister {
181 static const int kSizeInBytes = 4;
182 bool is_valid() const { return 0 <= code_ && code_ < 32; }
183 bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
192 void split_code(int* vm, int* m) const {
202 // Double word VFP register.
203 struct DwVfpRegister {
204 static const int kMaxNumRegisters = 32;
205 // A few double registers are reserved: one as a scratch register and one to
206 // hold 0.0, that does not fit in the immediate field of vmov instructions.
208 // d15: scratch register.
209 static const int kNumReservedRegisters = 2;
210 static const int kMaxNumAllocatableRegisters = kMaxNumRegisters -
211 kNumReservedRegisters;
212 static const int kSizeInBytes = 8;
214 // Note: the number of registers can be different at snapshot and run-time.
215 // Any code included in the snapshot must be able to run both with 16 or 32
217 inline static int NumRegisters();
218 inline static int NumReservedRegisters();
219 inline static int NumAllocatableRegisters();
221 // TODO(turbofan): This is a temporary work-around required because our
222 // register allocator does not yet support the aliasing of single/double
224 inline static int NumAllocatableAliasedRegisters();
226 inline static int ToAllocationIndex(DwVfpRegister reg);
227 static const char* AllocationIndexToString(int index);
228 inline static DwVfpRegister FromAllocationIndex(int index);
230 static DwVfpRegister from_code(int code) {
231 DwVfpRegister r = { code };
235 bool is_valid() const {
236 return 0 <= code_ && code_ < kMaxNumRegisters;
238 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
247 void split_code(int* vm, int* m) const {
249 *m = (code_ & 0x10) >> 4;
257 typedef DwVfpRegister DoubleRegister;
260 // Double word VFP register d0-15.
261 struct LowDwVfpRegister {
263 static const int kMaxNumLowRegisters = 16;
264 operator DwVfpRegister() const {
265 DwVfpRegister r = { code_ };
268 static LowDwVfpRegister from_code(int code) {
269 LowDwVfpRegister r = { code };
273 bool is_valid() const {
274 return 0 <= code_ && code_ < kMaxNumLowRegisters;
276 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
277 bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; }
282 SwVfpRegister low() const {
284 reg.code_ = code_ * 2;
286 DCHECK(reg.is_valid());
289 SwVfpRegister high() const {
291 reg.code_ = (code_ * 2) + 1;
293 DCHECK(reg.is_valid());
301 // Quad word NEON register.
302 struct QwNeonRegister {
303 static const int kMaxNumRegisters = 16;
305 static QwNeonRegister from_code(int code) {
306 QwNeonRegister r = { code };
310 bool is_valid() const {
311 return (0 <= code_) && (code_ < kMaxNumRegisters);
313 bool is(QwNeonRegister reg) const { return code_ == reg.code_; }
318 void split_code(int* vm, int* m) const {
320 int encoded_code = code_ << 1;
321 *m = (encoded_code & 0x10) >> 4;
322 *vm = encoded_code & 0x0F;
329 typedef QwNeonRegister QuadRegister;
332 // Support for the VFP registers s0 to s31 (d0 to d15).
333 // Note that "s(N):s(N+1)" is the same as "d(N/2)".
334 const SwVfpRegister s0 = { 0 };
335 const SwVfpRegister s1 = { 1 };
336 const SwVfpRegister s2 = { 2 };
337 const SwVfpRegister s3 = { 3 };
338 const SwVfpRegister s4 = { 4 };
339 const SwVfpRegister s5 = { 5 };
340 const SwVfpRegister s6 = { 6 };
341 const SwVfpRegister s7 = { 7 };
342 const SwVfpRegister s8 = { 8 };
343 const SwVfpRegister s9 = { 9 };
344 const SwVfpRegister s10 = { 10 };
345 const SwVfpRegister s11 = { 11 };
346 const SwVfpRegister s12 = { 12 };
347 const SwVfpRegister s13 = { 13 };
348 const SwVfpRegister s14 = { 14 };
349 const SwVfpRegister s15 = { 15 };
350 const SwVfpRegister s16 = { 16 };
351 const SwVfpRegister s17 = { 17 };
352 const SwVfpRegister s18 = { 18 };
353 const SwVfpRegister s19 = { 19 };
354 const SwVfpRegister s20 = { 20 };
355 const SwVfpRegister s21 = { 21 };
356 const SwVfpRegister s22 = { 22 };
357 const SwVfpRegister s23 = { 23 };
358 const SwVfpRegister s24 = { 24 };
359 const SwVfpRegister s25 = { 25 };
360 const SwVfpRegister s26 = { 26 };
361 const SwVfpRegister s27 = { 27 };
362 const SwVfpRegister s28 = { 28 };
363 const SwVfpRegister s29 = { 29 };
364 const SwVfpRegister s30 = { 30 };
365 const SwVfpRegister s31 = { 31 };
367 const DwVfpRegister no_dreg = { -1 };
368 const LowDwVfpRegister d0 = { 0 };
369 const LowDwVfpRegister d1 = { 1 };
370 const LowDwVfpRegister d2 = { 2 };
371 const LowDwVfpRegister d3 = { 3 };
372 const LowDwVfpRegister d4 = { 4 };
373 const LowDwVfpRegister d5 = { 5 };
374 const LowDwVfpRegister d6 = { 6 };
375 const LowDwVfpRegister d7 = { 7 };
376 const LowDwVfpRegister d8 = { 8 };
377 const LowDwVfpRegister d9 = { 9 };
378 const LowDwVfpRegister d10 = { 10 };
379 const LowDwVfpRegister d11 = { 11 };
380 const LowDwVfpRegister d12 = { 12 };
381 const LowDwVfpRegister d13 = { 13 };
382 const LowDwVfpRegister d14 = { 14 };
383 const LowDwVfpRegister d15 = { 15 };
384 const DwVfpRegister d16 = { 16 };
385 const DwVfpRegister d17 = { 17 };
386 const DwVfpRegister d18 = { 18 };
387 const DwVfpRegister d19 = { 19 };
388 const DwVfpRegister d20 = { 20 };
389 const DwVfpRegister d21 = { 21 };
390 const DwVfpRegister d22 = { 22 };
391 const DwVfpRegister d23 = { 23 };
392 const DwVfpRegister d24 = { 24 };
393 const DwVfpRegister d25 = { 25 };
394 const DwVfpRegister d26 = { 26 };
395 const DwVfpRegister d27 = { 27 };
396 const DwVfpRegister d28 = { 28 };
397 const DwVfpRegister d29 = { 29 };
398 const DwVfpRegister d30 = { 30 };
399 const DwVfpRegister d31 = { 31 };
401 const QwNeonRegister q0 = { 0 };
402 const QwNeonRegister q1 = { 1 };
403 const QwNeonRegister q2 = { 2 };
404 const QwNeonRegister q3 = { 3 };
405 const QwNeonRegister q4 = { 4 };
406 const QwNeonRegister q5 = { 5 };
407 const QwNeonRegister q6 = { 6 };
408 const QwNeonRegister q7 = { 7 };
409 const QwNeonRegister q8 = { 8 };
410 const QwNeonRegister q9 = { 9 };
411 const QwNeonRegister q10 = { 10 };
412 const QwNeonRegister q11 = { 11 };
413 const QwNeonRegister q12 = { 12 };
414 const QwNeonRegister q13 = { 13 };
415 const QwNeonRegister q14 = { 14 };
416 const QwNeonRegister q15 = { 15 };
419 // Aliases for double registers. Defined using #define instead of
420 // "static const DwVfpRegister&" because Clang complains otherwise when a
421 // compilation unit that includes this header doesn't use the variables.
422 #define kFirstCalleeSavedDoubleReg d8
423 #define kLastCalleeSavedDoubleReg d15
424 #define kDoubleRegZero d14
425 #define kScratchDoubleReg d15
428 // Coprocessor register
430 bool is_valid() const { return 0 <= code_ && code_ < 16; }
431 bool is(CRegister creg) const { return code_ == creg.code_; }
441 // Unfortunately we can't make this private in a struct.
446 const CRegister no_creg = { -1 };
448 const CRegister cr0 = { 0 };
449 const CRegister cr1 = { 1 };
450 const CRegister cr2 = { 2 };
451 const CRegister cr3 = { 3 };
452 const CRegister cr4 = { 4 };
453 const CRegister cr5 = { 5 };
454 const CRegister cr6 = { 6 };
455 const CRegister cr7 = { 7 };
456 const CRegister cr8 = { 8 };
457 const CRegister cr9 = { 9 };
458 const CRegister cr10 = { 10 };
459 const CRegister cr11 = { 11 };
460 const CRegister cr12 = { 12 };
461 const CRegister cr13 = { 13 };
462 const CRegister cr14 = { 14 };
463 const CRegister cr15 = { 15 };
466 // Coprocessor number
487 // -----------------------------------------------------------------------------
488 // Machine instruction Operands
490 // Class Operand represents a shifter operand in data processing instructions
491 class Operand BASE_EMBEDDED {
494 INLINE(explicit Operand(int32_t immediate,
495 RelocInfo::Mode rmode = RelocInfo::NONE32));
496 INLINE(static Operand Zero()) {
497 return Operand(static_cast<int32_t>(0));
499 INLINE(explicit Operand(const ExternalReference& f));
500 explicit Operand(Handle<Object> handle);
501 INLINE(explicit Operand(Smi* value));
504 INLINE(explicit Operand(Register rm));
506 // rm <shift_op> shift_imm
507 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
508 INLINE(static Operand SmiUntag(Register rm)) {
509 return Operand(rm, ASR, kSmiTagSize);
511 INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
512 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
513 return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
515 INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) {
516 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
517 return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
521 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
523 // Return true if this is a register operand.
524 INLINE(bool is_reg() const);
526 // Return the number of actual instructions required to implement the given
527 // instruction for this particular operand. This can be a single instruction,
528 // if no load into the ip register is necessary, or anything between 2 and 4
529 // instructions when we need to load from the constant pool (depending upon
530 // whether the constant pool entry is in the small or extended section). If
531 // the instruction this operand is used for is a MOV or MVN instruction the
532 // actual instruction to use is required for this calculation. For other
533 // instructions instr is ignored.
535 // The value returned is only valid as long as no entries are added to the
536 // constant pool between this call and the actual instruction being emitted.
537 int instructions_required(const Assembler* assembler, Instr instr = 0) const;
538 bool must_output_reloc_info(const Assembler* assembler) const;
540 inline int32_t immediate() const {
541 DCHECK(!rm_.is_valid());
545 Register rm() const { return rm_; }
546 Register rs() const { return rs_; }
547 ShiftOp shift_op() const { return shift_op_; }
553 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
554 int32_t imm32_; // valid if rm_ == no_reg
555 RelocInfo::Mode rmode_;
557 friend class Assembler;
561 // Class MemOperand represents a memory operand in load and store instructions
562 class MemOperand BASE_EMBEDDED {
564 // [rn +/- offset] Offset/NegOffset
565 // [rn +/- offset]! PreIndex/NegPreIndex
566 // [rn], +/- offset PostIndex/NegPostIndex
567 // offset is any signed 32-bit value; offset is first loaded to register ip if
568 // it does not fit the addressing mode (12-bit unsigned and sign bit)
569 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
571 // [rn +/- rm] Offset/NegOffset
572 // [rn +/- rm]! PreIndex/NegPreIndex
573 // [rn], +/- rm PostIndex/NegPostIndex
574 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
576 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
577 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
578 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
579 explicit MemOperand(Register rn, Register rm,
580 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
581 INLINE(static MemOperand PointerAddressFromSmiKey(Register array,
583 AddrMode am = Offset)) {
584 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
585 return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
588 void set_offset(int32_t offset) {
589 DCHECK(rm_.is(no_reg));
593 uint32_t offset() const {
594 DCHECK(rm_.is(no_reg));
598 Register rn() const { return rn_; }
599 Register rm() const { return rm_; }
600 AddrMode am() const { return am_; }
602 bool OffsetIsUint12Encodable() const {
603 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
607 Register rn_; // base
608 Register rm_; // register offset
609 int32_t offset_; // valid if rm_ == no_reg
611 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
612 AddrMode am_; // bits P, U, and W
614 friend class Assembler;
618 // Class NeonMemOperand represents a memory operand in load and
619 // store NEON instructions
620 class NeonMemOperand BASE_EMBEDDED {
622 // [rn {:align}] Offset
623 // [rn {:align}]! PostIndex
624 explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
626 // [rn {:align}], rm PostIndex
627 explicit NeonMemOperand(Register rn, Register rm, int align = 0);
629 Register rn() const { return rn_; }
630 Register rm() const { return rm_; }
631 int align() const { return align_; }
634 void SetAlignment(int align);
636 Register rn_; // base
637 Register rm_; // register increment
642 // Class NeonListOperand represents a list of NEON registers
643 class NeonListOperand BASE_EMBEDDED {
645 explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
646 DoubleRegister base() const { return base_; }
647 NeonListType type() const { return type_; }
649 DoubleRegister base_;
654 // Class used to build a constant pool.
655 class ConstantPoolBuilder BASE_EMBEDDED {
657 ConstantPoolBuilder();
658 ConstantPoolArray::LayoutSection AddEntry(Assembler* assm,
659 const RelocInfo& rinfo);
660 void Relocate(int pc_delta);
662 Handle<ConstantPoolArray> New(Isolate* isolate);
663 void Populate(Assembler* assm, ConstantPoolArray* constant_pool);
665 inline ConstantPoolArray::LayoutSection current_section() const {
666 return current_section_;
669 inline ConstantPoolArray::NumberOfEntries* number_of_entries(
670 ConstantPoolArray::LayoutSection section) {
671 return &number_of_entries_[section];
674 inline ConstantPoolArray::NumberOfEntries* small_entries() {
675 return number_of_entries(ConstantPoolArray::SMALL_SECTION);
678 inline ConstantPoolArray::NumberOfEntries* extended_entries() {
679 return number_of_entries(ConstantPoolArray::EXTENDED_SECTION);
683 struct ConstantPoolEntry {
684 ConstantPoolEntry(RelocInfo rinfo, ConstantPoolArray::LayoutSection section,
686 : rinfo_(rinfo), section_(section), merged_index_(merged_index) {}
689 ConstantPoolArray::LayoutSection section_;
693 ConstantPoolArray::Type GetConstantPoolType(RelocInfo::Mode rmode);
695 std::vector<ConstantPoolEntry> entries_;
696 ConstantPoolArray::LayoutSection current_section_;
697 ConstantPoolArray::NumberOfEntries number_of_entries_[2];
703 const VmovIndex VmovIndexLo = { 0 };
704 const VmovIndex VmovIndexHi = { 1 };
706 class Assembler : public AssemblerBase {
708 // Create an assembler. Instructions and relocation information are emitted
709 // into a buffer, with the instructions starting from the beginning and the
710 // relocation information starting from the end of the buffer. See CodeDesc
711 // for a detailed comment on the layout (globals.h).
713 // If the provided buffer is NULL, the assembler allocates and grows its own
714 // buffer, and buffer_size determines the initial buffer size. The buffer is
715 // owned by the assembler and deallocated upon destruction of the assembler.
717 // If the provided buffer is not NULL, the assembler uses the provided buffer
718 // for code generation and assumes its size to be buffer_size. If the buffer
719 // is too small, a fatal error occurs. No deallocation of the buffer is done
720 // upon destruction of the assembler.
721 Assembler(Isolate* isolate, void* buffer, int buffer_size);
722 virtual ~Assembler();
724 // GetCode emits any pending (non-emitted) code and fills the descriptor
725 // desc. GetCode() is idempotent; it returns the same result if no other
726 // Assembler functions are invoked in between GetCode() calls.
727 void GetCode(CodeDesc* desc);
729 // Label operations & relative jumps (PPUM Appendix D)
731 // Takes a branch opcode (cc) and a label (L) and generates
732 // either a backward branch or a forward branch and links it
733 // to the label fixup chain. Usage:
735 // Label L; // unbound label
736 // j(cc, &L); // forward branch to unbound label
737 // bind(&L); // bind label to the current pc
738 // j(cc, &L); // backward branch to bound label
739 // bind(&L); // illegal: a label may be bound only once
741 // Note: The same Label can be used for forward and backward branches
742 // but it may be bound only once.
744 void bind(Label* L); // binds an unbound label L to the current code position
746 // Returns the branch offset to the given label from the current code position
747 // Links the label to the current position if it is still unbound
748 // Manages the jump elimination optimization if the second parameter is true.
749 int branch_offset(Label* L, bool jump_elimination_allowed);
751 // Returns true if the given pc address is the start of a constant pool load
752 // instruction sequence.
753 INLINE(static bool is_constant_pool_load(Address pc));
755 // Return the address in the constant pool of the code target address used by
756 // the branch/call instruction at pc, or the object in a mov.
757 INLINE(static Address constant_pool_entry_address(
758 Address pc, ConstantPoolArray* constant_pool));
760 // Read/Modify the code target address in the branch/call instruction at pc.
761 INLINE(static Address target_address_at(Address pc,
762 ConstantPoolArray* constant_pool));
763 INLINE(static void set_target_address_at(Address pc,
764 ConstantPoolArray* constant_pool,
766 ICacheFlushMode icache_flush_mode =
767 FLUSH_ICACHE_IF_NEEDED));
768 INLINE(static Address target_address_at(Address pc, Code* code)) {
769 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
770 return target_address_at(pc, constant_pool);
772 INLINE(static void set_target_address_at(Address pc,
775 ICacheFlushMode icache_flush_mode =
776 FLUSH_ICACHE_IF_NEEDED)) {
777 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
778 set_target_address_at(pc, constant_pool, target, icache_flush_mode);
781 // Return the code target address at a call site from the return address
782 // of that call in the instruction stream.
783 INLINE(static Address target_address_from_return_address(Address pc));
785 // Given the address of the beginning of a call, return the address
786 // in the instruction stream that the call will return from.
787 INLINE(static Address return_address_from_call_start(Address pc));
789 // Return the code target address of the patch debug break slot
790 INLINE(static Address break_address_from_return_address(Address pc));
792 // This sets the branch destination (which is in the constant pool on ARM).
793 // This is for calls and branches within generated code.
794 inline static void deserialization_set_special_target_at(
795 Address constant_pool_entry, Code* code, Address target);
797 // This sets the internal reference at the pc.
798 inline static void deserialization_set_target_internal_reference_at(
799 Address pc, Address target,
800 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
802 // Here we are patching the address in the constant pool, not the actual call
803 // instruction. The address in the constant pool is the same size as a
805 static const int kSpecialTargetSize = kPointerSize;
807 // Size of an instruction.
808 static const int kInstrSize = sizeof(Instr);
810 // Distance between start of patched return sequence and the emitted address
812 // Patched return sequence is:
813 // ldr ip, [pc, #0] @ emited address and start
815 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize;
817 // Distance between start of patched debug break slot and the emitted address
819 // Patched debug break slot code is:
820 // ldr ip, [pc, #0] @ emited address and start
822 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
824 static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize;
826 // Difference between address of current opcode and value read from pc
828 static const int kPcLoadDelta = 8;
830 static const int kJSReturnSequenceInstructions = 4;
831 static const int kJSReturnSequenceLength =
832 kJSReturnSequenceInstructions * kInstrSize;
833 static const int kDebugBreakSlotInstructions = 3;
834 static const int kDebugBreakSlotLength =
835 kDebugBreakSlotInstructions * kInstrSize;
837 // ---------------------------------------------------------------------------
840 // Insert the smallest number of nop instructions
841 // possible to align the pc offset to a multiple
842 // of m. m must be a power of 2 (>= 4).
844 // Aligns code to something that's optimal for a jump target for the platform.
845 void CodeTargetAlign();
847 // Branch instructions
848 void b(int branch_offset, Condition cond = al);
849 void bl(int branch_offset, Condition cond = al);
850 void blx(int branch_offset); // v5 and above
851 void blx(Register target, Condition cond = al); // v5 and above
852 void bx(Register target, Condition cond = al); // v5 and above, plus v4t
854 // Convenience branch instructions using labels
855 void b(Label* L, Condition cond = al) {
856 b(branch_offset(L, cond == al), cond);
858 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); }
859 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); }
860 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); }
861 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
863 // Data-processing instructions
865 void and_(Register dst, Register src1, const Operand& src2,
866 SBit s = LeaveCC, Condition cond = al);
868 void eor(Register dst, Register src1, const Operand& src2,
869 SBit s = LeaveCC, Condition cond = al);
871 void sub(Register dst, Register src1, const Operand& src2,
872 SBit s = LeaveCC, Condition cond = al);
873 void sub(Register dst, Register src1, Register src2,
874 SBit s = LeaveCC, Condition cond = al) {
875 sub(dst, src1, Operand(src2), s, cond);
878 void rsb(Register dst, Register src1, const Operand& src2,
879 SBit s = LeaveCC, Condition cond = al);
881 void add(Register dst, Register src1, const Operand& src2,
882 SBit s = LeaveCC, Condition cond = al);
883 void add(Register dst, Register src1, Register src2,
884 SBit s = LeaveCC, Condition cond = al) {
885 add(dst, src1, Operand(src2), s, cond);
888 void adc(Register dst, Register src1, const Operand& src2,
889 SBit s = LeaveCC, Condition cond = al);
891 void sbc(Register dst, Register src1, const Operand& src2,
892 SBit s = LeaveCC, Condition cond = al);
894 void rsc(Register dst, Register src1, const Operand& src2,
895 SBit s = LeaveCC, Condition cond = al);
897 void tst(Register src1, const Operand& src2, Condition cond = al);
898 void tst(Register src1, Register src2, Condition cond = al) {
899 tst(src1, Operand(src2), cond);
902 void teq(Register src1, const Operand& src2, Condition cond = al);
904 void cmp(Register src1, const Operand& src2, Condition cond = al);
905 void cmp(Register src1, Register src2, Condition cond = al) {
906 cmp(src1, Operand(src2), cond);
908 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
910 void cmn(Register src1, const Operand& src2, Condition cond = al);
912 void orr(Register dst, Register src1, const Operand& src2,
913 SBit s = LeaveCC, Condition cond = al);
914 void orr(Register dst, Register src1, Register src2,
915 SBit s = LeaveCC, Condition cond = al) {
916 orr(dst, src1, Operand(src2), s, cond);
919 void mov(Register dst, const Operand& src,
920 SBit s = LeaveCC, Condition cond = al);
921 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
922 mov(dst, Operand(src), s, cond);
925 // Load the position of the label relative to the generated code object
926 // pointer in a register.
927 void mov_label_offset(Register dst, Label* label);
929 // ARMv7 instructions for loading a 32 bit immediate in two instructions.
930 // The constant for movw and movt should be in the range 0-0xffff.
931 void movw(Register reg, uint32_t immediate, Condition cond = al);
932 void movt(Register reg, uint32_t immediate, Condition cond = al);
934 void bic(Register dst, Register src1, const Operand& src2,
935 SBit s = LeaveCC, Condition cond = al);
937 void mvn(Register dst, const Operand& src,
938 SBit s = LeaveCC, Condition cond = al);
940 // Shift instructions
942 void asr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
943 Condition cond = al) {
945 mov(dst, Operand(src1, ASR, src2.rm()), s, cond);
947 mov(dst, Operand(src1, ASR, src2.immediate()), s, cond);
951 void lsl(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
952 Condition cond = al) {
954 mov(dst, Operand(src1, LSL, src2.rm()), s, cond);
956 mov(dst, Operand(src1, LSL, src2.immediate()), s, cond);
960 void lsr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
961 Condition cond = al) {
963 mov(dst, Operand(src1, LSR, src2.rm()), s, cond);
965 mov(dst, Operand(src1, LSR, src2.immediate()), s, cond);
969 // Multiply instructions
971 void mla(Register dst, Register src1, Register src2, Register srcA,
972 SBit s = LeaveCC, Condition cond = al);
974 void mls(Register dst, Register src1, Register src2, Register srcA,
975 Condition cond = al);
977 void sdiv(Register dst, Register src1, Register src2,
978 Condition cond = al);
980 void udiv(Register dst, Register src1, Register src2, Condition cond = al);
982 void mul(Register dst, Register src1, Register src2,
983 SBit s = LeaveCC, Condition cond = al);
985 void smmla(Register dst, Register src1, Register src2, Register srcA,
986 Condition cond = al);
988 void smmul(Register dst, Register src1, Register src2, Condition cond = al);
990 void smlal(Register dstL, Register dstH, Register src1, Register src2,
991 SBit s = LeaveCC, Condition cond = al);
993 void smull(Register dstL, Register dstH, Register src1, Register src2,
994 SBit s = LeaveCC, Condition cond = al);
996 void umlal(Register dstL, Register dstH, Register src1, Register src2,
997 SBit s = LeaveCC, Condition cond = al);
999 void umull(Register dstL, Register dstH, Register src1, Register src2,
1000 SBit s = LeaveCC, Condition cond = al);
1002 // Miscellaneous arithmetic instructions
1004 void clz(Register dst, Register src, Condition cond = al); // v5 and above
1006 // Saturating instructions. v6 and above.
1008 // Unsigned saturate.
1010 // Saturate an optionally shifted signed value to an unsigned range.
1012 // usat dst, #satpos, src
1013 // usat dst, #satpos, src, lsl #sh
1014 // usat dst, #satpos, src, asr #sh
1016 // Register dst will contain:
1019 // (1 << satpos) - 1, if s > ((1 << satpos) - 1)
1022 // where s is the contents of src after shifting (if used.)
1023 void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
1025 // Bitfield manipulation instructions. v7 and above.
1027 void ubfx(Register dst, Register src, int lsb, int width,
1028 Condition cond = al);
1030 void sbfx(Register dst, Register src, int lsb, int width,
1031 Condition cond = al);
1033 void bfc(Register dst, int lsb, int width, Condition cond = al);
1035 void bfi(Register dst, Register src, int lsb, int width,
1036 Condition cond = al);
1038 void pkhbt(Register dst, Register src1, const Operand& src2,
1039 Condition cond = al);
1041 void pkhtb(Register dst, Register src1, const Operand& src2,
1042 Condition cond = al);
1044 void sxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
1045 void sxtab(Register dst, Register src1, Register src2, int rotate = 0,
1046 Condition cond = al);
1047 void sxth(Register dst, Register src, int rotate = 0, Condition cond = al);
1048 void sxtah(Register dst, Register src1, Register src2, int rotate = 0,
1049 Condition cond = al);
1051 void uxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
1052 void uxtab(Register dst, Register src1, Register src2, int rotate = 0,
1053 Condition cond = al);
1054 void uxtb16(Register dst, Register src, int rotate = 0, Condition cond = al);
1055 void uxth(Register dst, Register src, int rotate = 0, Condition cond = al);
1056 void uxtah(Register dst, Register src1, Register src2, int rotate = 0,
1057 Condition cond = al);
1059 // Status register access instructions
1061 void mrs(Register dst, SRegister s, Condition cond = al);
1062 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
1064 // Load/Store instructions
1065 void ldr(Register dst, const MemOperand& src, Condition cond = al);
1066 void str(Register src, const MemOperand& dst, Condition cond = al);
1067 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
1068 void strb(Register src, const MemOperand& dst, Condition cond = al);
1069 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
1070 void strh(Register src, const MemOperand& dst, Condition cond = al);
1071 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
1072 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
1073 void ldrd(Register dst1,
1075 const MemOperand& src, Condition cond = al);
1076 void strd(Register src1,
1078 const MemOperand& dst, Condition cond = al);
1080 // Preload instructions
1081 void pld(const MemOperand& address);
1083 // Load/Store multiple instructions
1084 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
1085 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
1087 // Exception-generating instructions and debugging support
1088 void stop(const char* msg,
1089 Condition cond = al,
1090 int32_t code = kDefaultStopCode);
1092 void bkpt(uint32_t imm16); // v5 and above
1093 void svc(uint32_t imm24, Condition cond = al);
1095 // Coprocessor instructions
1097 void cdp(Coprocessor coproc, int opcode_1,
1098 CRegister crd, CRegister crn, CRegister crm,
1099 int opcode_2, Condition cond = al);
1101 void cdp2(Coprocessor coproc, int opcode_1,
1102 CRegister crd, CRegister crn, CRegister crm,
1103 int opcode_2); // v5 and above
1105 void mcr(Coprocessor coproc, int opcode_1,
1106 Register rd, CRegister crn, CRegister crm,
1107 int opcode_2 = 0, Condition cond = al);
1109 void mcr2(Coprocessor coproc, int opcode_1,
1110 Register rd, CRegister crn, CRegister crm,
1111 int opcode_2 = 0); // v5 and above
1113 void mrc(Coprocessor coproc, int opcode_1,
1114 Register rd, CRegister crn, CRegister crm,
1115 int opcode_2 = 0, Condition cond = al);
1117 void mrc2(Coprocessor coproc, int opcode_1,
1118 Register rd, CRegister crn, CRegister crm,
1119 int opcode_2 = 0); // v5 and above
1121 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
1122 LFlag l = Short, Condition cond = al);
1123 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
1124 LFlag l = Short, Condition cond = al);
1126 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
1127 LFlag l = Short); // v5 and above
1128 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
1129 LFlag l = Short); // v5 and above
1132 // All these APIs support S0 to S31 and D0 to D31.
1134 void vldr(const DwVfpRegister dst,
1135 const Register base,
1137 const Condition cond = al);
1138 void vldr(const DwVfpRegister dst,
1139 const MemOperand& src,
1140 const Condition cond = al);
1142 void vldr(const SwVfpRegister dst,
1143 const Register base,
1145 const Condition cond = al);
1146 void vldr(const SwVfpRegister dst,
1147 const MemOperand& src,
1148 const Condition cond = al);
1150 void vstr(const DwVfpRegister src,
1151 const Register base,
1153 const Condition cond = al);
1154 void vstr(const DwVfpRegister src,
1155 const MemOperand& dst,
1156 const Condition cond = al);
1158 void vstr(const SwVfpRegister src,
1159 const Register base,
1161 const Condition cond = al);
1162 void vstr(const SwVfpRegister src,
1163 const MemOperand& dst,
1164 const Condition cond = al);
1166 void vldm(BlockAddrMode am,
1168 DwVfpRegister first,
1170 Condition cond = al);
1172 void vstm(BlockAddrMode am,
1174 DwVfpRegister first,
1176 Condition cond = al);
1178 void vldm(BlockAddrMode am,
1180 SwVfpRegister first,
1182 Condition cond = al);
1184 void vstm(BlockAddrMode am,
1186 SwVfpRegister first,
1188 Condition cond = al);
1190 void vmov(const SwVfpRegister dst, float imm);
1191 void vmov(const DwVfpRegister dst,
1193 const Register scratch = no_reg);
1194 void vmov(const SwVfpRegister dst,
1195 const SwVfpRegister src,
1196 const Condition cond = al);
1197 void vmov(const DwVfpRegister dst,
1198 const DwVfpRegister src,
1199 const Condition cond = al);
1200 void vmov(const DwVfpRegister dst,
1201 const VmovIndex index,
1203 const Condition cond = al);
1204 void vmov(const Register dst,
1205 const VmovIndex index,
1206 const DwVfpRegister src,
1207 const Condition cond = al);
1208 void vmov(const DwVfpRegister dst,
1209 const Register src1,
1210 const Register src2,
1211 const Condition cond = al);
1212 void vmov(const Register dst1,
1213 const Register dst2,
1214 const DwVfpRegister src,
1215 const Condition cond = al);
1216 void vmov(const SwVfpRegister dst,
1218 const Condition cond = al);
1219 void vmov(const Register dst,
1220 const SwVfpRegister src,
1221 const Condition cond = al);
1222 void vcvt_f64_s32(const DwVfpRegister dst,
1223 const SwVfpRegister src,
1224 VFPConversionMode mode = kDefaultRoundToZero,
1225 const Condition cond = al);
1226 void vcvt_f32_s32(const SwVfpRegister dst,
1227 const SwVfpRegister src,
1228 VFPConversionMode mode = kDefaultRoundToZero,
1229 const Condition cond = al);
1230 void vcvt_f64_u32(const DwVfpRegister dst,
1231 const SwVfpRegister src,
1232 VFPConversionMode mode = kDefaultRoundToZero,
1233 const Condition cond = al);
1234 void vcvt_s32_f64(const SwVfpRegister dst,
1235 const DwVfpRegister src,
1236 VFPConversionMode mode = kDefaultRoundToZero,
1237 const Condition cond = al);
1238 void vcvt_u32_f64(const SwVfpRegister dst,
1239 const DwVfpRegister src,
1240 VFPConversionMode mode = kDefaultRoundToZero,
1241 const Condition cond = al);
1242 void vcvt_f64_f32(const DwVfpRegister dst,
1243 const SwVfpRegister src,
1244 VFPConversionMode mode = kDefaultRoundToZero,
1245 const Condition cond = al);
1246 void vcvt_f32_f64(const SwVfpRegister dst,
1247 const DwVfpRegister src,
1248 VFPConversionMode mode = kDefaultRoundToZero,
1249 const Condition cond = al);
1250 void vcvt_f64_s32(const DwVfpRegister dst,
1252 const Condition cond = al);
1254 void vneg(const DwVfpRegister dst,
1255 const DwVfpRegister src,
1256 const Condition cond = al);
1257 void vabs(const DwVfpRegister dst,
1258 const DwVfpRegister src,
1259 const Condition cond = al);
1260 void vadd(const DwVfpRegister dst,
1261 const DwVfpRegister src1,
1262 const DwVfpRegister src2,
1263 const Condition cond = al);
1264 void vsub(const DwVfpRegister dst,
1265 const DwVfpRegister src1,
1266 const DwVfpRegister src2,
1267 const Condition cond = al);
1268 void vmul(const DwVfpRegister dst,
1269 const DwVfpRegister src1,
1270 const DwVfpRegister src2,
1271 const Condition cond = al);
1272 void vmla(const DwVfpRegister dst,
1273 const DwVfpRegister src1,
1274 const DwVfpRegister src2,
1275 const Condition cond = al);
1276 void vmls(const DwVfpRegister dst,
1277 const DwVfpRegister src1,
1278 const DwVfpRegister src2,
1279 const Condition cond = al);
1280 void vdiv(const DwVfpRegister dst,
1281 const DwVfpRegister src1,
1282 const DwVfpRegister src2,
1283 const Condition cond = al);
1284 void vcmp(const DwVfpRegister src1,
1285 const DwVfpRegister src2,
1286 const Condition cond = al);
1287 void vcmp(const DwVfpRegister src1,
1289 const Condition cond = al);
1290 void vmrs(const Register dst,
1291 const Condition cond = al);
1292 void vmsr(const Register dst,
1293 const Condition cond = al);
1294 void vsqrt(const DwVfpRegister dst,
1295 const DwVfpRegister src,
1296 const Condition cond = al);
1298 // ARMv8 rounding instructions.
1299 void vrinta(const DwVfpRegister dst, const DwVfpRegister src);
1300 void vrintn(const DwVfpRegister dst, const DwVfpRegister src);
1301 void vrintm(const DwVfpRegister dst, const DwVfpRegister src);
1302 void vrintp(const DwVfpRegister dst, const DwVfpRegister src);
1303 void vrintz(const DwVfpRegister dst, const DwVfpRegister src,
1304 const Condition cond = al);
1306 // Support for NEON.
1307 // All these APIs support D0 to D31 and Q0 to Q15.
1309 void vld1(NeonSize size,
1310 const NeonListOperand& dst,
1311 const NeonMemOperand& src);
1312 void vst1(NeonSize size,
1313 const NeonListOperand& src,
1314 const NeonMemOperand& dst);
1315 void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
1317 // Pseudo instructions
1319 // Different nop operations are used by the code generator to detect certain
1320 // states of the generated code.
1321 enum NopMarkerTypes {
1322 NON_MARKING_NOP = 0,
1325 PROPERTY_ACCESS_INLINED,
1326 PROPERTY_ACCESS_INLINED_CONTEXT,
1327 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1330 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1333 void nop(int type = 0); // 0 is the default non-marking type.
1335 void push(Register src, Condition cond = al) {
1336 str(src, MemOperand(sp, 4, NegPreIndex), cond);
1339 void pop(Register dst, Condition cond = al) {
1340 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1344 add(sp, sp, Operand(kPointerSize));
1347 // Jump unconditionally to given label.
1348 void jmp(Label* L) { b(L, al); }
1350 // Check the code size generated from label to here.
1351 int SizeOfCodeGeneratedSince(Label* label) {
1352 return pc_offset() - label->pos();
1355 // Check the number of instructions generated from label to here.
1356 int InstructionsGeneratedSince(Label* label) {
1357 return SizeOfCodeGeneratedSince(label) / kInstrSize;
1360 // Check whether an immediate fits an addressing mode 1 instruction.
1361 static bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1363 // Check whether an immediate fits an addressing mode 2 instruction.
1364 bool ImmediateFitsAddrMode2Instruction(int32_t imm32);
1366 // Class for scoping postponing the constant pool generation.
1367 class BlockConstPoolScope {
1369 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1370 assem_->StartBlockConstPool();
1372 ~BlockConstPoolScope() {
1373 assem_->EndBlockConstPool();
1379 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1384 // Mark address of the ExitJSFrame code.
1385 void RecordJSReturn();
1387 // Mark address of a debug break slot.
1388 void RecordDebugBreakSlot();
1390 // Record the AST id of the CallIC being compiled, so that it can be placed
1391 // in the relocation information.
1392 void SetRecordedAstId(TypeFeedbackId ast_id) {
1393 DCHECK(recorded_ast_id_.IsNone());
1394 recorded_ast_id_ = ast_id;
1397 TypeFeedbackId RecordedAstId() {
1398 DCHECK(!recorded_ast_id_.IsNone());
1399 return recorded_ast_id_;
1402 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
1404 // Record a comment relocation entry that can be used by a disassembler.
1405 // Use --code-comments to enable.
1406 void RecordComment(const char* msg);
1408 // Record a deoptimization reason that can be used by a log or cpu profiler.
1409 // Use --trace-deopt to enable.
1410 void RecordDeoptReason(const int reason, const SourcePosition position);
1412 // Record the emission of a constant pool.
1414 // The emission of constant pool depends on the size of the code generated and
1415 // the number of RelocInfo recorded.
1416 // The Debug mechanism needs to map code offsets between two versions of a
1417 // function, compiled with and without debugger support (see for example
1418 // Debug::PrepareForBreakPoints()).
1419 // Compiling functions with debugger support generates additional code
1420 // (DebugCodegen::GenerateSlot()). This may affect the emission of the
1421 // constant pools and cause the version of the code with debugger support to
1422 // have constant pools generated in different places.
1423 // Recording the position and size of emitted constant pools allows to
1424 // correctly compute the offset mappings between the different versions of a
1425 // function in all situations.
1427 // The parameter indicates the size of the constant pool (in bytes), including
1428 // the marker and branch over the data.
1429 void RecordConstPool(int size);
1431 // Writes a single byte or word of data in the code stream. Used
1432 // for inline tables, e.g., jump-tables. The constant pool should be
1433 // emitted before any use of db and dd to ensure that constant pools
1434 // are not emitted as part of the tables generated.
1435 void db(uint8_t data);
1436 void dd(uint32_t data);
1437 void dd(Label* label);
1439 // Emits the address of the code stub's first instruction.
1440 void emit_code_stub_address(Code* stub);
1442 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1444 // Read/patch instructions
1445 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1446 void instr_at_put(int pos, Instr instr) {
1447 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1449 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1450 static void instr_at_put(byte* pc, Instr instr) {
1451 *reinterpret_cast<Instr*>(pc) = instr;
1453 static Condition GetCondition(Instr instr);
1454 static bool IsBranch(Instr instr);
1455 static int GetBranchOffset(Instr instr);
1456 static bool IsLdrRegisterImmediate(Instr instr);
1457 static bool IsVldrDRegisterImmediate(Instr instr);
1458 static Instr GetConsantPoolLoadPattern();
1459 static Instr GetConsantPoolLoadMask();
1460 static bool IsLdrPpRegOffset(Instr instr);
1461 static Instr GetLdrPpRegOffsetPattern();
1462 static bool IsLdrPpImmediateOffset(Instr instr);
1463 static bool IsVldrDPpImmediateOffset(Instr instr);
1464 static int GetLdrRegisterImmediateOffset(Instr instr);
1465 static int GetVldrDRegisterImmediateOffset(Instr instr);
1466 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
1467 static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
1468 static bool IsStrRegisterImmediate(Instr instr);
1469 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1470 static bool IsAddRegisterImmediate(Instr instr);
1471 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
1472 static Register GetRd(Instr instr);
1473 static Register GetRn(Instr instr);
1474 static Register GetRm(Instr instr);
1475 static bool IsPush(Instr instr);
1476 static bool IsPop(Instr instr);
1477 static bool IsStrRegFpOffset(Instr instr);
1478 static bool IsLdrRegFpOffset(Instr instr);
1479 static bool IsStrRegFpNegOffset(Instr instr);
1480 static bool IsLdrRegFpNegOffset(Instr instr);
1481 static bool IsLdrPcImmediateOffset(Instr instr);
1482 static bool IsVldrDPcImmediateOffset(Instr instr);
1483 static bool IsBlxReg(Instr instr);
1484 static bool IsBlxIp(Instr instr);
1485 static bool IsTstImmediate(Instr instr);
1486 static bool IsCmpRegister(Instr instr);
1487 static bool IsCmpImmediate(Instr instr);
1488 static Register GetCmpImmediateRegister(Instr instr);
1489 static int GetCmpImmediateRawImmediate(Instr instr);
1490 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1491 static bool IsMovImmed(Instr instr);
1492 static bool IsOrrImmed(Instr instr);
1493 static bool IsMovT(Instr instr);
1494 static Instr GetMovTPattern();
1495 static bool IsMovW(Instr instr);
1496 static Instr GetMovWPattern();
1497 static Instr EncodeMovwImmediate(uint32_t immediate);
1498 static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate);
1499 static int DecodeShiftImm(Instr instr);
1500 static Instr PatchShiftImm(Instr instr, int immed);
1502 // Constants in pools are accessed via pc relative addressing, which can
1503 // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
1504 // PC-relative loads, thereby defining a maximum distance between the
1505 // instruction and the accessed constant.
1506 static const int kMaxDistToIntPool = 4*KB;
1507 static const int kMaxDistToFPPool = 1*KB;
1508 // All relocations could be integer, it therefore acts as the limit.
1509 static const int kMaxNumPending32RelocInfo = kMaxDistToIntPool/kInstrSize;
1510 static const int kMaxNumPending64RelocInfo = kMaxDistToFPPool/kInstrSize;
1512 // Postpone the generation of the constant pool for the specified number of
1514 void BlockConstPoolFor(int instructions);
1516 // Check if is time to emit a constant pool.
1517 void CheckConstPool(bool force_emit, bool require_jump);
1519 // Allocate a constant pool of the correct size for the generated code.
1520 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
1522 // Generate the constant pool for the generated code.
1523 void PopulateConstantPool(ConstantPoolArray* constant_pool);
1525 bool use_extended_constant_pool() const {
1526 return constant_pool_builder_.current_section() ==
1527 ConstantPoolArray::EXTENDED_SECTION;
1532 // Relocation for a type-recording IC has the AST id added to it. This
1533 // member variable is a way to pass the information from the call site to
1534 // the relocation info.
1535 TypeFeedbackId recorded_ast_id_;
1537 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1539 // Decode branch instruction at pos and return branch target pos
1540 int target_at(int pos);
1542 // Patch branch instruction at pos to branch to given branch target pos
1543 void target_at_put(int pos, int target_pos);
1545 // Prevent contant pool emission until EndBlockConstPool is called.
1546 // Call to this function can be nested but must be followed by an equal
1547 // number of call to EndBlockConstpool.
1548 void StartBlockConstPool() {
1549 if (const_pool_blocked_nesting_++ == 0) {
1550 // Prevent constant pool checks happening by setting the next check to
1551 // the biggest possible offset.
1552 next_buffer_check_ = kMaxInt;
1556 // Resume constant pool emission. Need to be called as many time as
1557 // StartBlockConstPool to have an effect.
1558 void EndBlockConstPool() {
1559 if (--const_pool_blocked_nesting_ == 0) {
1561 // Max pool start (if we need a jump and an alignment).
1562 int start = pc_offset() + kInstrSize + 2 * kPointerSize;
1563 // Check the constant pool hasn't been blocked for too long.
1564 DCHECK((num_pending_32_bit_reloc_info_ == 0) ||
1565 (start + num_pending_64_bit_reloc_info_ * kDoubleSize <
1566 (first_const_pool_32_use_ + kMaxDistToIntPool)));
1567 DCHECK((num_pending_64_bit_reloc_info_ == 0) ||
1568 (start < (first_const_pool_64_use_ + kMaxDistToFPPool)));
1571 // * no_const_pool_before_ >= next_buffer_check_ and the emission is
1573 // * no_const_pool_before_ < next_buffer_check_ and the next emit will
1575 next_buffer_check_ = no_const_pool_before_;
1579 bool is_const_pool_blocked() const {
1580 return (const_pool_blocked_nesting_ > 0) ||
1581 (pc_offset() < no_const_pool_before_);
1585 int next_buffer_check_; // pc offset of next buffer check
1588 // The relocation writer's position is at least kGap bytes below the end of
1589 // the generated instructions. This is so that multi-instruction sequences do
1590 // not have to check for overflow. The same is true for writes of large
1591 // relocation info entries.
1592 static const int kGap = 32;
1594 // Constant pool generation
1595 // Pools are emitted in the instruction stream, preferably after unconditional
1596 // jumps or after returns from functions (in dead code locations).
1597 // If a long code sequence does not contain unconditional jumps, it is
1598 // necessary to emit the constant pool before the pool gets too far from the
1599 // location it is accessed from. In this case, we emit a jump over the emitted
1601 // Constants in the pool may be addresses of functions that gets relocated;
1602 // if so, a relocation info entry is associated to the constant pool entry.
1604 // Repeated checking whether the constant pool should be emitted is rather
1605 // expensive. By default we only check again once a number of instructions
1606 // has been generated. That also means that the sizing of the buffers is not
1607 // an exact science, and that we rely on some slop to not overrun buffers.
1608 static const int kCheckPoolIntervalInst = 32;
1609 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
1612 // Emission of the constant pool may be blocked in some code sequences.
1613 int const_pool_blocked_nesting_; // Block emission if this is not zero.
1614 int no_const_pool_before_; // Block emission before this pc offset.
1616 // Keep track of the first instruction requiring a constant pool entry
1617 // since the previous constant pool was emitted.
1618 int first_const_pool_32_use_;
1619 int first_const_pool_64_use_;
1621 // Relocation info generation
1622 // Each relocation is encoded as a variable size value
1623 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1624 RelocInfoWriter reloc_info_writer;
1626 // Relocation info records are also used during code generation as temporary
1627 // containers for constants and code target addresses until they are emitted
1628 // to the constant pool. These pending relocation info records are temporarily
1629 // stored in a separate buffer until a constant pool is emitted.
1630 // If every instruction in a long sequence is accessing the pool, we need one
1631 // pending relocation entry per instruction.
1633 // The buffers of pending relocation info.
1634 RelocInfo pending_32_bit_reloc_info_[kMaxNumPending32RelocInfo];
1635 RelocInfo pending_64_bit_reloc_info_[kMaxNumPending64RelocInfo];
1636 // Number of pending reloc info entries in the 32 bits buffer.
1637 int num_pending_32_bit_reloc_info_;
1638 // Number of pending reloc info entries in the 64 bits buffer.
1639 int num_pending_64_bit_reloc_info_;
1641 ConstantPoolBuilder constant_pool_builder_;
1643 // The bound position, before this we cannot do instruction elimination.
1644 int last_bound_pos_;
1647 inline void CheckBuffer();
1649 inline void emit(Instr x);
1651 // 32-bit immediate values
1652 void move_32_bit_immediate(Register rd,
1654 Condition cond = al);
1656 // Instruction generation
1657 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1658 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1659 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1660 void addrmod4(Instr instr, Register rn, RegList rl);
1661 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1664 void print(Label* L);
1665 void bind_to(Label* L, int pos);
1666 void next(Label* L);
1668 enum UseConstantPoolMode {
1670 DONT_USE_CONSTANT_POOL
1673 // Record reloc info for current pc_
1674 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1675 void RecordRelocInfo(const RelocInfo& rinfo);
1676 ConstantPoolArray::LayoutSection ConstantPoolAddEntry(const RelocInfo& rinfo);
1678 friend class RelocInfo;
1679 friend class CodePatcher;
1680 friend class BlockConstPoolScope;
1681 PositionsRecorder positions_recorder_;
1682 friend class PositionsRecorder;
1683 friend class EnsureSpace;
1687 class EnsureSpace BASE_EMBEDDED {
1689 explicit EnsureSpace(Assembler* assembler) {
1690 assembler->CheckBuffer();
1695 } } // namespace v8::internal
1697 #endif // V8_ARM_ASSEMBLER_ARM_H_