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_
43 #include "assembler.h"
44 #include "constants-arm.h"
45 #include "serialize.h"
50 // CpuFeatures keeps track of which features are supported by the target CPU.
51 // Supported features must be enabled by a CpuFeatureScope before use.
52 class CpuFeatures : public AllStatic {
54 // Detect features of the target CPU. Set safe defaults if the serializer
55 // is enabled (snapshots must be portable).
58 // Display target use when compiling.
59 static void PrintTarget();
62 static void PrintFeatures();
64 // Check whether a feature is supported by the target CPU.
65 static bool IsSupported(CpuFeature f) {
67 return Check(f, supported_);
70 static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
72 return Check(f, found_by_runtime_probing_only_);
75 static bool IsSafeForSnapshot(CpuFeature f) {
76 return Check(f, cross_compile_) ||
78 (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
81 static unsigned cache_line_size() { return cache_line_size_; }
83 static bool VerifyCrossCompiling() {
84 return cross_compile_ == 0;
87 static bool VerifyCrossCompiling(CpuFeature f) {
88 unsigned mask = flag2set(f);
89 return cross_compile_ == 0 ||
90 (cross_compile_ & mask) == mask;
94 static bool Check(CpuFeature f, unsigned set) {
95 return (set & flag2set(f)) != 0;
98 static unsigned flag2set(CpuFeature f) {
103 static bool initialized_;
105 static unsigned supported_;
106 static unsigned found_by_runtime_probing_only_;
107 static unsigned cache_line_size_;
109 static unsigned cross_compile_;
111 friend class ExternalReference;
112 friend class PlatformFeatureScope;
113 DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
119 // 1) We would prefer to use an enum, but enum values are assignment-
120 // compatible with int, which has caused code-generation bugs.
122 // 2) We would prefer to use a class instead of a struct but we don't like
123 // the register initialization to depend on the particular initialization
124 // order (which appears to be different on OS X, Linux, and Windows for the
125 // installed versions of C++ we tried). Using a struct permits C-style
126 // "initialization". Also, the Register objects cannot be const as this
127 // forces initialization stubs in MSVC, making us dependent on initialization
130 // 3) By not using an enum, we are possibly preventing the compiler from
131 // doing certain constant folds, which may significantly reduce the
132 // code generated for some assembly instructions (because they boil down
133 // to a few constants). If this is a problem, we could change the code
134 // such that we use an enum in optimized mode, and the struct in debug
135 // mode. This way we get the compile-time error checking in debug mode
136 // and best performance in optimized code.
138 // These constants are used in several locations, including static initializers
139 const int kRegister_no_reg_Code = -1;
140 const int kRegister_r0_Code = 0;
141 const int kRegister_r1_Code = 1;
142 const int kRegister_r2_Code = 2;
143 const int kRegister_r3_Code = 3;
144 const int kRegister_r4_Code = 4;
145 const int kRegister_r5_Code = 5;
146 const int kRegister_r6_Code = 6;
147 const int kRegister_r7_Code = 7;
148 const int kRegister_r8_Code = 8;
149 const int kRegister_r9_Code = 9;
150 const int kRegister_r10_Code = 10;
151 const int kRegister_fp_Code = 11;
152 const int kRegister_ip_Code = 12;
153 const int kRegister_sp_Code = 13;
154 const int kRegister_lr_Code = 14;
155 const int kRegister_pc_Code = 15;
159 static const int kNumRegisters = 16;
160 static const int kMaxNumAllocatableRegisters =
161 FLAG_enable_ool_constant_pool ? 8 : 9;
162 static const int kSizeInBytes = 4;
164 inline static int NumAllocatableRegisters();
166 static int ToAllocationIndex(Register reg) {
167 ASSERT(reg.code() < kMaxNumAllocatableRegisters);
171 static Register FromAllocationIndex(int index) {
172 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
173 return from_code(index);
176 static const char* AllocationIndexToString(int index) {
177 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
178 const char* const names[] = {
189 if (FLAG_enable_ool_constant_pool && (index >= 7)) {
190 return names[index + 1];
195 static Register from_code(int code) {
196 Register r = { code };
200 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
201 bool is(Register reg) const { return code_ == reg.code_; }
211 void set_code(int code) {
216 // Unfortunately we can't make this private in a struct.
220 const Register no_reg = { kRegister_no_reg_Code };
222 const Register r0 = { kRegister_r0_Code };
223 const Register r1 = { kRegister_r1_Code };
224 const Register r2 = { kRegister_r2_Code };
225 const Register r3 = { kRegister_r3_Code };
226 const Register r4 = { kRegister_r4_Code };
227 const Register r5 = { kRegister_r5_Code };
228 const Register r6 = { kRegister_r6_Code };
229 // Used as constant pool pointer register if FLAG_enable_ool_constant_pool.
230 const Register r7 = { kRegister_r7_Code };
231 // Used as context register.
232 const Register r8 = { kRegister_r8_Code };
233 // Used as lithium codegen scratch register.
234 const Register r9 = { kRegister_r9_Code };
235 // Used as roots register.
236 const Register r10 = { kRegister_r10_Code };
237 const Register fp = { kRegister_fp_Code };
238 const Register ip = { kRegister_ip_Code };
239 const Register sp = { kRegister_sp_Code };
240 const Register lr = { kRegister_lr_Code };
241 const Register pc = { kRegister_pc_Code };
243 // Single word VFP register.
244 struct SwVfpRegister {
245 static const int kSizeInBytes = 4;
246 bool is_valid() const { return 0 <= code_ && code_ < 32; }
247 bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
256 void split_code(int* vm, int* m) const {
266 // Double word VFP register.
267 struct DwVfpRegister {
268 static const int kMaxNumRegisters = 32;
269 // A few double registers are reserved: one as a scratch register and one to
270 // hold 0.0, that does not fit in the immediate field of vmov instructions.
272 // d15: scratch register.
273 static const int kNumReservedRegisters = 2;
274 static const int kMaxNumAllocatableRegisters = kMaxNumRegisters -
275 kNumReservedRegisters;
276 static const int kSizeInBytes = 8;
278 // Note: the number of registers can be different at snapshot and run-time.
279 // Any code included in the snapshot must be able to run both with 16 or 32
281 inline static int NumRegisters();
282 inline static int NumReservedRegisters();
283 inline static int NumAllocatableRegisters();
285 inline static int ToAllocationIndex(DwVfpRegister reg);
286 static const char* AllocationIndexToString(int index);
287 inline static DwVfpRegister FromAllocationIndex(int index);
289 static DwVfpRegister from_code(int code) {
290 DwVfpRegister r = { code };
294 bool is_valid() const {
295 return 0 <= code_ && code_ < kMaxNumRegisters;
297 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
306 void split_code(int* vm, int* m) const {
308 *m = (code_ & 0x10) >> 4;
316 typedef DwVfpRegister DoubleRegister;
319 // Double word VFP register d0-15.
320 struct LowDwVfpRegister {
322 static const int kMaxNumLowRegisters = 16;
323 operator DwVfpRegister() const {
324 DwVfpRegister r = { code_ };
327 static LowDwVfpRegister from_code(int code) {
328 LowDwVfpRegister r = { code };
332 bool is_valid() const {
333 return 0 <= code_ && code_ < kMaxNumLowRegisters;
335 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
336 bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; }
341 SwVfpRegister low() const {
343 reg.code_ = code_ * 2;
345 ASSERT(reg.is_valid());
348 SwVfpRegister high() const {
350 reg.code_ = (code_ * 2) + 1;
352 ASSERT(reg.is_valid());
360 // Quad word NEON register.
361 struct QwNeonRegister {
362 static const int kMaxNumRegisters = 16;
364 static QwNeonRegister from_code(int code) {
365 QwNeonRegister r = { code };
369 bool is_valid() const {
370 return (0 <= code_) && (code_ < kMaxNumRegisters);
372 bool is(QwNeonRegister reg) const { return code_ == reg.code_; }
377 void split_code(int* vm, int* m) const {
379 *m = (code_ & 0x10) >> 4;
387 typedef QwNeonRegister QuadRegister;
390 // Support for the VFP registers s0 to s31 (d0 to d15).
391 // Note that "s(N):s(N+1)" is the same as "d(N/2)".
392 const SwVfpRegister s0 = { 0 };
393 const SwVfpRegister s1 = { 1 };
394 const SwVfpRegister s2 = { 2 };
395 const SwVfpRegister s3 = { 3 };
396 const SwVfpRegister s4 = { 4 };
397 const SwVfpRegister s5 = { 5 };
398 const SwVfpRegister s6 = { 6 };
399 const SwVfpRegister s7 = { 7 };
400 const SwVfpRegister s8 = { 8 };
401 const SwVfpRegister s9 = { 9 };
402 const SwVfpRegister s10 = { 10 };
403 const SwVfpRegister s11 = { 11 };
404 const SwVfpRegister s12 = { 12 };
405 const SwVfpRegister s13 = { 13 };
406 const SwVfpRegister s14 = { 14 };
407 const SwVfpRegister s15 = { 15 };
408 const SwVfpRegister s16 = { 16 };
409 const SwVfpRegister s17 = { 17 };
410 const SwVfpRegister s18 = { 18 };
411 const SwVfpRegister s19 = { 19 };
412 const SwVfpRegister s20 = { 20 };
413 const SwVfpRegister s21 = { 21 };
414 const SwVfpRegister s22 = { 22 };
415 const SwVfpRegister s23 = { 23 };
416 const SwVfpRegister s24 = { 24 };
417 const SwVfpRegister s25 = { 25 };
418 const SwVfpRegister s26 = { 26 };
419 const SwVfpRegister s27 = { 27 };
420 const SwVfpRegister s28 = { 28 };
421 const SwVfpRegister s29 = { 29 };
422 const SwVfpRegister s30 = { 30 };
423 const SwVfpRegister s31 = { 31 };
425 const DwVfpRegister no_dreg = { -1 };
426 const LowDwVfpRegister d0 = { 0 };
427 const LowDwVfpRegister d1 = { 1 };
428 const LowDwVfpRegister d2 = { 2 };
429 const LowDwVfpRegister d3 = { 3 };
430 const LowDwVfpRegister d4 = { 4 };
431 const LowDwVfpRegister d5 = { 5 };
432 const LowDwVfpRegister d6 = { 6 };
433 const LowDwVfpRegister d7 = { 7 };
434 const LowDwVfpRegister d8 = { 8 };
435 const LowDwVfpRegister d9 = { 9 };
436 const LowDwVfpRegister d10 = { 10 };
437 const LowDwVfpRegister d11 = { 11 };
438 const LowDwVfpRegister d12 = { 12 };
439 const LowDwVfpRegister d13 = { 13 };
440 const LowDwVfpRegister d14 = { 14 };
441 const LowDwVfpRegister d15 = { 15 };
442 const DwVfpRegister d16 = { 16 };
443 const DwVfpRegister d17 = { 17 };
444 const DwVfpRegister d18 = { 18 };
445 const DwVfpRegister d19 = { 19 };
446 const DwVfpRegister d20 = { 20 };
447 const DwVfpRegister d21 = { 21 };
448 const DwVfpRegister d22 = { 22 };
449 const DwVfpRegister d23 = { 23 };
450 const DwVfpRegister d24 = { 24 };
451 const DwVfpRegister d25 = { 25 };
452 const DwVfpRegister d26 = { 26 };
453 const DwVfpRegister d27 = { 27 };
454 const DwVfpRegister d28 = { 28 };
455 const DwVfpRegister d29 = { 29 };
456 const DwVfpRegister d30 = { 30 };
457 const DwVfpRegister d31 = { 31 };
459 const QwNeonRegister q0 = { 0 };
460 const QwNeonRegister q1 = { 1 };
461 const QwNeonRegister q2 = { 2 };
462 const QwNeonRegister q3 = { 3 };
463 const QwNeonRegister q4 = { 4 };
464 const QwNeonRegister q5 = { 5 };
465 const QwNeonRegister q6 = { 6 };
466 const QwNeonRegister q7 = { 7 };
467 const QwNeonRegister q8 = { 8 };
468 const QwNeonRegister q9 = { 9 };
469 const QwNeonRegister q10 = { 10 };
470 const QwNeonRegister q11 = { 11 };
471 const QwNeonRegister q12 = { 12 };
472 const QwNeonRegister q13 = { 13 };
473 const QwNeonRegister q14 = { 14 };
474 const QwNeonRegister q15 = { 15 };
477 // Aliases for double registers. Defined using #define instead of
478 // "static const DwVfpRegister&" because Clang complains otherwise when a
479 // compilation unit that includes this header doesn't use the variables.
480 #define kFirstCalleeSavedDoubleReg d8
481 #define kLastCalleeSavedDoubleReg d15
482 #define kDoubleRegZero d14
483 #define kScratchDoubleReg d15
486 // Coprocessor register
488 bool is_valid() const { return 0 <= code_ && code_ < 16; }
489 bool is(CRegister creg) const { return code_ == creg.code_; }
499 // Unfortunately we can't make this private in a struct.
504 const CRegister no_creg = { -1 };
506 const CRegister cr0 = { 0 };
507 const CRegister cr1 = { 1 };
508 const CRegister cr2 = { 2 };
509 const CRegister cr3 = { 3 };
510 const CRegister cr4 = { 4 };
511 const CRegister cr5 = { 5 };
512 const CRegister cr6 = { 6 };
513 const CRegister cr7 = { 7 };
514 const CRegister cr8 = { 8 };
515 const CRegister cr9 = { 9 };
516 const CRegister cr10 = { 10 };
517 const CRegister cr11 = { 11 };
518 const CRegister cr12 = { 12 };
519 const CRegister cr13 = { 13 };
520 const CRegister cr14 = { 14 };
521 const CRegister cr15 = { 15 };
524 // Coprocessor number
545 // -----------------------------------------------------------------------------
546 // Machine instruction Operands
548 // Class Operand represents a shifter operand in data processing instructions
549 class Operand BASE_EMBEDDED {
552 INLINE(explicit Operand(int32_t immediate,
553 RelocInfo::Mode rmode = RelocInfo::NONE32));
554 INLINE(static Operand Zero()) {
555 return Operand(static_cast<int32_t>(0));
557 INLINE(explicit Operand(const ExternalReference& f));
558 explicit Operand(Handle<Object> handle);
559 INLINE(explicit Operand(Smi* value));
562 INLINE(explicit Operand(Register rm));
564 // rm <shift_op> shift_imm
565 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
566 INLINE(static Operand SmiUntag(Register rm)) {
567 return Operand(rm, ASR, kSmiTagSize);
569 INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
570 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
571 return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
573 INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) {
574 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
575 return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
579 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
581 // Return true if this is a register operand.
582 INLINE(bool is_reg() const);
584 // Return true if this operand fits in one instruction so that no
585 // 2-instruction solution with a load into the ip register is necessary. If
586 // the instruction this operand is used for is a MOV or MVN instruction the
587 // actual instruction to use is required for this calculation. For other
588 // instructions instr is ignored.
589 bool is_single_instruction(const Assembler* assembler, Instr instr = 0) const;
590 bool must_output_reloc_info(const Assembler* assembler) const;
592 inline int32_t immediate() const {
593 ASSERT(!rm_.is_valid());
597 Register rm() const { return rm_; }
598 Register rs() const { return rs_; }
599 ShiftOp shift_op() const { return shift_op_; }
605 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
606 int32_t imm32_; // valid if rm_ == no_reg
607 RelocInfo::Mode rmode_;
609 friend class Assembler;
613 // Class MemOperand represents a memory operand in load and store instructions
614 class MemOperand BASE_EMBEDDED {
616 // [rn +/- offset] Offset/NegOffset
617 // [rn +/- offset]! PreIndex/NegPreIndex
618 // [rn], +/- offset PostIndex/NegPostIndex
619 // offset is any signed 32-bit value; offset is first loaded to register ip if
620 // it does not fit the addressing mode (12-bit unsigned and sign bit)
621 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
623 // [rn +/- rm] Offset/NegOffset
624 // [rn +/- rm]! PreIndex/NegPreIndex
625 // [rn], +/- rm PostIndex/NegPostIndex
626 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
628 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
629 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
630 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
631 explicit MemOperand(Register rn, Register rm,
632 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
633 INLINE(static MemOperand PointerAddressFromSmiKey(Register array,
635 AddrMode am = Offset)) {
636 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
637 return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
640 void set_offset(int32_t offset) {
641 ASSERT(rm_.is(no_reg));
645 uint32_t offset() const {
646 ASSERT(rm_.is(no_reg));
650 Register rn() const { return rn_; }
651 Register rm() const { return rm_; }
652 AddrMode am() const { return am_; }
654 bool OffsetIsUint12Encodable() const {
655 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
659 Register rn_; // base
660 Register rm_; // register offset
661 int32_t offset_; // valid if rm_ == no_reg
663 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
664 AddrMode am_; // bits P, U, and W
666 friend class Assembler;
670 // Class NeonMemOperand represents a memory operand in load and
671 // store NEON instructions
672 class NeonMemOperand BASE_EMBEDDED {
674 // [rn {:align}] Offset
675 // [rn {:align}]! PostIndex
676 explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
678 // [rn {:align}], rm PostIndex
679 explicit NeonMemOperand(Register rn, Register rm, int align = 0);
681 Register rn() const { return rn_; }
682 Register rm() const { return rm_; }
683 int align() const { return align_; }
686 void SetAlignment(int align);
688 Register rn_; // base
689 Register rm_; // register increment
694 // Class NeonListOperand represents a list of NEON registers
695 class NeonListOperand BASE_EMBEDDED {
697 explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
698 DoubleRegister base() const { return base_; }
699 NeonListType type() const { return type_; }
701 DoubleRegister base_;
705 extern const Instr kMovLrPc;
706 extern const Instr kLdrPCMask;
707 extern const Instr kLdrPCPattern;
708 extern const Instr kBlxRegMask;
709 extern const Instr kBlxRegPattern;
710 extern const Instr kBlxIp;
712 extern const Instr kMovMvnMask;
713 extern const Instr kMovMvnPattern;
714 extern const Instr kMovMvnFlip;
716 extern const Instr kMovLeaveCCMask;
717 extern const Instr kMovLeaveCCPattern;
718 extern const Instr kMovwMask;
719 extern const Instr kMovwPattern;
720 extern const Instr kMovwLeaveCCFlip;
722 extern const Instr kCmpCmnMask;
723 extern const Instr kCmpCmnPattern;
724 extern const Instr kCmpCmnFlip;
725 extern const Instr kAddSubFlip;
726 extern const Instr kAndBicFlip;
731 const VmovIndex VmovIndexLo = { 0 };
732 const VmovIndex VmovIndexHi = { 1 };
734 class Assembler : public AssemblerBase {
736 // Create an assembler. Instructions and relocation information are emitted
737 // into a buffer, with the instructions starting from the beginning and the
738 // relocation information starting from the end of the buffer. See CodeDesc
739 // for a detailed comment on the layout (globals.h).
741 // If the provided buffer is NULL, the assembler allocates and grows its own
742 // buffer, and buffer_size determines the initial buffer size. The buffer is
743 // owned by the assembler and deallocated upon destruction of the assembler.
745 // If the provided buffer is not NULL, the assembler uses the provided buffer
746 // for code generation and assumes its size to be buffer_size. If the buffer
747 // is too small, a fatal error occurs. No deallocation of the buffer is done
748 // upon destruction of the assembler.
749 Assembler(Isolate* isolate, void* buffer, int buffer_size);
750 virtual ~Assembler();
752 // GetCode emits any pending (non-emitted) code and fills the descriptor
753 // desc. GetCode() is idempotent; it returns the same result if no other
754 // Assembler functions are invoked in between GetCode() calls.
755 void GetCode(CodeDesc* desc);
757 // Label operations & relative jumps (PPUM Appendix D)
759 // Takes a branch opcode (cc) and a label (L) and generates
760 // either a backward branch or a forward branch and links it
761 // to the label fixup chain. Usage:
763 // Label L; // unbound label
764 // j(cc, &L); // forward branch to unbound label
765 // bind(&L); // bind label to the current pc
766 // j(cc, &L); // backward branch to bound label
767 // bind(&L); // illegal: a label may be bound only once
769 // Note: The same Label can be used for forward and backward branches
770 // but it may be bound only once.
772 void bind(Label* L); // binds an unbound label L to the current code position
774 // Returns the branch offset to the given label from the current code position
775 // Links the label to the current position if it is still unbound
776 // Manages the jump elimination optimization if the second parameter is true.
777 int branch_offset(Label* L, bool jump_elimination_allowed);
779 // Return the address in the constant pool of the code target address used by
780 // the branch/call instruction at pc, or the object in a mov.
781 INLINE(static Address target_pointer_address_at(Address pc));
783 // Read/Modify the code target address in the branch/call instruction at pc.
784 INLINE(static Address target_address_at(Address pc));
785 INLINE(static void set_target_address_at(Address pc, Address target));
787 // Return the code target address at a call site from the return address
788 // of that call in the instruction stream.
789 INLINE(static Address target_address_from_return_address(Address pc));
791 // Given the address of the beginning of a call, return the address
792 // in the instruction stream that the call will return from.
793 INLINE(static Address return_address_from_call_start(Address pc));
795 // This sets the branch destination (which is in the constant pool on ARM).
796 // This is for calls and branches within generated code.
797 inline static void deserialization_set_special_target_at(
798 Address constant_pool_entry, Address target);
800 // Here we are patching the address in the constant pool, not the actual call
801 // instruction. The address in the constant pool is the same size as a
803 static const int kSpecialTargetSize = kPointerSize;
805 // Size of an instruction.
806 static const int kInstrSize = sizeof(Instr);
808 // Distance between start of patched return sequence and the emitted address
810 // Patched return sequence is:
811 // ldr ip, [pc, #0] @ emited address and start
813 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize;
815 // Distance between start of patched debug break slot and the emitted address
817 // Patched debug break slot code is:
818 // ldr ip, [pc, #0] @ emited address and start
820 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
822 static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize;
824 // Difference between address of current opcode and value read from pc
826 static const int kPcLoadDelta = 8;
828 static const int kJSReturnSequenceInstructions = 4;
829 static const int kDebugBreakSlotInstructions = 3;
830 static const int kDebugBreakSlotLength =
831 kDebugBreakSlotInstructions * kInstrSize;
833 // ---------------------------------------------------------------------------
836 // Insert the smallest number of nop instructions
837 // possible to align the pc offset to a multiple
838 // of m. m must be a power of 2 (>= 4).
840 // Aligns code to something that's optimal for a jump target for the platform.
841 void CodeTargetAlign();
843 // Branch instructions
844 void b(int branch_offset, Condition cond = al);
845 void bl(int branch_offset, Condition cond = al);
846 void blx(int branch_offset); // v5 and above
847 void blx(Register target, Condition cond = al); // v5 and above
848 void bx(Register target, Condition cond = al); // v5 and above, plus v4t
850 // Convenience branch instructions using labels
851 void b(Label* L, Condition cond = al) {
852 b(branch_offset(L, cond == al), cond);
854 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); }
855 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); }
856 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); }
857 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
859 // Data-processing instructions
861 void and_(Register dst, Register src1, const Operand& src2,
862 SBit s = LeaveCC, Condition cond = al);
864 void eor(Register dst, Register src1, const Operand& src2,
865 SBit s = LeaveCC, Condition cond = al);
867 void sub(Register dst, Register src1, const Operand& src2,
868 SBit s = LeaveCC, Condition cond = al);
869 void sub(Register dst, Register src1, Register src2,
870 SBit s = LeaveCC, Condition cond = al) {
871 sub(dst, src1, Operand(src2), s, cond);
874 void rsb(Register dst, Register src1, const Operand& src2,
875 SBit s = LeaveCC, Condition cond = al);
877 void add(Register dst, Register src1, const Operand& src2,
878 SBit s = LeaveCC, Condition cond = al);
879 void add(Register dst, Register src1, Register src2,
880 SBit s = LeaveCC, Condition cond = al) {
881 add(dst, src1, Operand(src2), s, cond);
884 void adc(Register dst, Register src1, const Operand& src2,
885 SBit s = LeaveCC, Condition cond = al);
887 void sbc(Register dst, Register src1, const Operand& src2,
888 SBit s = LeaveCC, Condition cond = al);
890 void rsc(Register dst, Register src1, const Operand& src2,
891 SBit s = LeaveCC, Condition cond = al);
893 void tst(Register src1, const Operand& src2, Condition cond = al);
894 void tst(Register src1, Register src2, Condition cond = al) {
895 tst(src1, Operand(src2), cond);
898 void teq(Register src1, const Operand& src2, Condition cond = al);
900 void cmp(Register src1, const Operand& src2, Condition cond = al);
901 void cmp(Register src1, Register src2, Condition cond = al) {
902 cmp(src1, Operand(src2), cond);
904 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
906 void cmn(Register src1, const Operand& src2, Condition cond = al);
908 void orr(Register dst, Register src1, const Operand& src2,
909 SBit s = LeaveCC, Condition cond = al);
910 void orr(Register dst, Register src1, Register src2,
911 SBit s = LeaveCC, Condition cond = al) {
912 orr(dst, src1, Operand(src2), s, cond);
915 void mov(Register dst, const Operand& src,
916 SBit s = LeaveCC, Condition cond = al);
917 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
918 mov(dst, Operand(src), s, cond);
921 // Load the position of the label relative to the generated code object
922 // pointer in a register.
923 void mov_label_offset(Register dst, Label* label);
925 // ARMv7 instructions for loading a 32 bit immediate in two instructions.
926 // This may actually emit a different mov instruction, but on an ARMv7 it
927 // is guaranteed to only emit one instruction.
928 void movw(Register reg, uint32_t immediate, Condition cond = al);
929 // The constant for movt should be in the range 0-0xffff.
930 void movt(Register reg, uint32_t immediate, Condition cond = al);
932 void bic(Register dst, Register src1, const Operand& src2,
933 SBit s = LeaveCC, Condition cond = al);
935 void mvn(Register dst, const Operand& src,
936 SBit s = LeaveCC, Condition cond = al);
938 // Multiply instructions
940 void mla(Register dst, Register src1, Register src2, Register srcA,
941 SBit s = LeaveCC, Condition cond = al);
943 void mls(Register dst, Register src1, Register src2, Register srcA,
944 Condition cond = al);
946 void sdiv(Register dst, Register src1, Register src2,
947 Condition cond = al);
949 void mul(Register dst, Register src1, Register src2,
950 SBit s = LeaveCC, Condition cond = al);
952 void smlal(Register dstL, Register dstH, Register src1, Register src2,
953 SBit s = LeaveCC, Condition cond = al);
955 void smull(Register dstL, Register dstH, Register src1, Register src2,
956 SBit s = LeaveCC, Condition cond = al);
958 void umlal(Register dstL, Register dstH, Register src1, Register src2,
959 SBit s = LeaveCC, Condition cond = al);
961 void umull(Register dstL, Register dstH, Register src1, Register src2,
962 SBit s = LeaveCC, Condition cond = al);
964 // Miscellaneous arithmetic instructions
966 void clz(Register dst, Register src, Condition cond = al); // v5 and above
968 // Saturating instructions. v6 and above.
970 // Unsigned saturate.
972 // Saturate an optionally shifted signed value to an unsigned range.
974 // usat dst, #satpos, src
975 // usat dst, #satpos, src, lsl #sh
976 // usat dst, #satpos, src, asr #sh
978 // Register dst will contain:
981 // (1 << satpos) - 1, if s > ((1 << satpos) - 1)
984 // where s is the contents of src after shifting (if used.)
985 void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
987 // Bitfield manipulation instructions. v7 and above.
989 void ubfx(Register dst, Register src, int lsb, int width,
990 Condition cond = al);
992 void sbfx(Register dst, Register src, int lsb, int width,
993 Condition cond = al);
995 void bfc(Register dst, int lsb, int width, Condition cond = al);
997 void bfi(Register dst, Register src, int lsb, int width,
998 Condition cond = al);
1000 void pkhbt(Register dst, Register src1, const Operand& src2,
1001 Condition cond = al);
1003 void pkhtb(Register dst, Register src1, const Operand& src2,
1004 Condition cond = al);
1006 void uxtb(Register dst, const Operand& src, Condition cond = al);
1008 void uxtab(Register dst, Register src1, const Operand& src2,
1009 Condition cond = al);
1011 void uxtb16(Register dst, const Operand& src, Condition cond = al);
1013 // Status register access instructions
1015 void mrs(Register dst, SRegister s, Condition cond = al);
1016 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
1018 // Load/Store instructions
1019 void ldr(Register dst, const MemOperand& src, Condition cond = al);
1020 void str(Register src, const MemOperand& dst, Condition cond = al);
1021 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
1022 void strb(Register src, const MemOperand& dst, Condition cond = al);
1023 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
1024 void strh(Register src, const MemOperand& dst, Condition cond = al);
1025 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
1026 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
1027 void ldrd(Register dst1,
1029 const MemOperand& src, Condition cond = al);
1030 void strd(Register src1,
1032 const MemOperand& dst, Condition cond = al);
1034 // Preload instructions
1035 void pld(const MemOperand& address);
1037 // Load/Store multiple instructions
1038 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
1039 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
1041 // Exception-generating instructions and debugging support
1042 void stop(const char* msg,
1043 Condition cond = al,
1044 int32_t code = kDefaultStopCode);
1046 void bkpt(uint32_t imm16); // v5 and above
1047 void svc(uint32_t imm24, Condition cond = al);
1049 // Coprocessor instructions
1051 void cdp(Coprocessor coproc, int opcode_1,
1052 CRegister crd, CRegister crn, CRegister crm,
1053 int opcode_2, Condition cond = al);
1055 void cdp2(Coprocessor coproc, int opcode_1,
1056 CRegister crd, CRegister crn, CRegister crm,
1057 int opcode_2); // v5 and above
1059 void mcr(Coprocessor coproc, int opcode_1,
1060 Register rd, CRegister crn, CRegister crm,
1061 int opcode_2 = 0, Condition cond = al);
1063 void mcr2(Coprocessor coproc, int opcode_1,
1064 Register rd, CRegister crn, CRegister crm,
1065 int opcode_2 = 0); // v5 and above
1067 void mrc(Coprocessor coproc, int opcode_1,
1068 Register rd, CRegister crn, CRegister crm,
1069 int opcode_2 = 0, Condition cond = al);
1071 void mrc2(Coprocessor coproc, int opcode_1,
1072 Register rd, CRegister crn, CRegister crm,
1073 int opcode_2 = 0); // v5 and above
1075 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
1076 LFlag l = Short, Condition cond = al);
1077 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
1078 LFlag l = Short, Condition cond = al);
1080 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
1081 LFlag l = Short); // v5 and above
1082 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
1083 LFlag l = Short); // v5 and above
1086 // All these APIs support S0 to S31 and D0 to D31.
1088 void vldr(const DwVfpRegister dst,
1089 const Register base,
1091 const Condition cond = al);
1092 void vldr(const DwVfpRegister dst,
1093 const MemOperand& src,
1094 const Condition cond = al);
1096 void vldr(const SwVfpRegister dst,
1097 const Register base,
1099 const Condition cond = al);
1100 void vldr(const SwVfpRegister dst,
1101 const MemOperand& src,
1102 const Condition cond = al);
1104 void vstr(const DwVfpRegister src,
1105 const Register base,
1107 const Condition cond = al);
1108 void vstr(const DwVfpRegister src,
1109 const MemOperand& dst,
1110 const Condition cond = al);
1112 void vstr(const SwVfpRegister src,
1113 const Register base,
1115 const Condition cond = al);
1116 void vstr(const SwVfpRegister src,
1117 const MemOperand& dst,
1118 const Condition cond = al);
1120 void vldm(BlockAddrMode am,
1122 DwVfpRegister first,
1124 Condition cond = al);
1126 void vstm(BlockAddrMode am,
1128 DwVfpRegister first,
1130 Condition cond = al);
1132 void vldm(BlockAddrMode am,
1134 SwVfpRegister first,
1136 Condition cond = al);
1138 void vstm(BlockAddrMode am,
1140 SwVfpRegister first,
1142 Condition cond = al);
1144 void vmov(const DwVfpRegister dst,
1146 const Register scratch = no_reg);
1147 void vmov(const SwVfpRegister dst,
1148 const SwVfpRegister src,
1149 const Condition cond = al);
1150 void vmov(const DwVfpRegister dst,
1151 const DwVfpRegister src,
1152 const Condition cond = al);
1153 void vmov(const DwVfpRegister dst,
1154 const VmovIndex index,
1156 const Condition cond = al);
1157 void vmov(const Register dst,
1158 const VmovIndex index,
1159 const DwVfpRegister src,
1160 const Condition cond = al);
1161 void vmov(const DwVfpRegister dst,
1162 const Register src1,
1163 const Register src2,
1164 const Condition cond = al);
1165 void vmov(const Register dst1,
1166 const Register dst2,
1167 const DwVfpRegister src,
1168 const Condition cond = al);
1169 void vmov(const SwVfpRegister dst,
1171 const Condition cond = al);
1172 void vmov(const Register dst,
1173 const SwVfpRegister src,
1174 const Condition cond = al);
1175 void vcvt_f64_s32(const DwVfpRegister dst,
1176 const SwVfpRegister src,
1177 VFPConversionMode mode = kDefaultRoundToZero,
1178 const Condition cond = al);
1179 void vcvt_f32_s32(const SwVfpRegister dst,
1180 const SwVfpRegister src,
1181 VFPConversionMode mode = kDefaultRoundToZero,
1182 const Condition cond = al);
1183 void vcvt_f64_u32(const DwVfpRegister dst,
1184 const SwVfpRegister src,
1185 VFPConversionMode mode = kDefaultRoundToZero,
1186 const Condition cond = al);
1187 void vcvt_s32_f64(const SwVfpRegister dst,
1188 const DwVfpRegister src,
1189 VFPConversionMode mode = kDefaultRoundToZero,
1190 const Condition cond = al);
1191 void vcvt_u32_f64(const SwVfpRegister dst,
1192 const DwVfpRegister src,
1193 VFPConversionMode mode = kDefaultRoundToZero,
1194 const Condition cond = al);
1195 void vcvt_f64_f32(const DwVfpRegister dst,
1196 const SwVfpRegister src,
1197 VFPConversionMode mode = kDefaultRoundToZero,
1198 const Condition cond = al);
1199 void vcvt_f32_f64(const SwVfpRegister dst,
1200 const DwVfpRegister src,
1201 VFPConversionMode mode = kDefaultRoundToZero,
1202 const Condition cond = al);
1203 void vcvt_f64_s32(const DwVfpRegister dst,
1205 const Condition cond = al);
1207 void vneg(const DwVfpRegister dst,
1208 const DwVfpRegister src,
1209 const Condition cond = al);
1210 void vabs(const DwVfpRegister dst,
1211 const DwVfpRegister src,
1212 const Condition cond = al);
1213 void vadd(const DwVfpRegister dst,
1214 const DwVfpRegister src1,
1215 const DwVfpRegister src2,
1216 const Condition cond = al);
1217 void vsub(const DwVfpRegister dst,
1218 const DwVfpRegister src1,
1219 const DwVfpRegister src2,
1220 const Condition cond = al);
1221 void vmul(const DwVfpRegister dst,
1222 const DwVfpRegister src1,
1223 const DwVfpRegister src2,
1224 const Condition cond = al);
1225 void vmla(const DwVfpRegister dst,
1226 const DwVfpRegister src1,
1227 const DwVfpRegister src2,
1228 const Condition cond = al);
1229 void vmls(const DwVfpRegister dst,
1230 const DwVfpRegister src1,
1231 const DwVfpRegister src2,
1232 const Condition cond = al);
1233 void vdiv(const DwVfpRegister dst,
1234 const DwVfpRegister src1,
1235 const DwVfpRegister src2,
1236 const Condition cond = al);
1237 void vcmp(const DwVfpRegister src1,
1238 const DwVfpRegister src2,
1239 const Condition cond = al);
1240 void vcmp(const DwVfpRegister src1,
1242 const Condition cond = al);
1243 void vmrs(const Register dst,
1244 const Condition cond = al);
1245 void vmsr(const Register dst,
1246 const Condition cond = al);
1247 void vsqrt(const DwVfpRegister dst,
1248 const DwVfpRegister src,
1249 const Condition cond = al);
1251 // Support for NEON.
1252 // All these APIs support D0 to D31 and Q0 to Q15.
1254 void vld1(NeonSize size,
1255 const NeonListOperand& dst,
1256 const NeonMemOperand& src);
1257 void vst1(NeonSize size,
1258 const NeonListOperand& src,
1259 const NeonMemOperand& dst);
1260 void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
1262 // Pseudo instructions
1264 // Different nop operations are used by the code generator to detect certain
1265 // states of the generated code.
1266 enum NopMarkerTypes {
1267 NON_MARKING_NOP = 0,
1270 PROPERTY_ACCESS_INLINED,
1271 PROPERTY_ACCESS_INLINED_CONTEXT,
1272 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1275 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1278 void nop(int type = 0); // 0 is the default non-marking type.
1280 void push(Register src, Condition cond = al) {
1281 str(src, MemOperand(sp, 4, NegPreIndex), cond);
1284 void pop(Register dst, Condition cond = al) {
1285 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1289 add(sp, sp, Operand(kPointerSize));
1292 // Jump unconditionally to given label.
1293 void jmp(Label* L) { b(L, al); }
1295 static bool use_immediate_embedded_pointer_loads(
1296 const Assembler* assembler) {
1297 return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
1298 (assembler == NULL || !assembler->predictable_code_size());
1301 // Check the code size generated from label to here.
1302 int SizeOfCodeGeneratedSince(Label* label) {
1303 return pc_offset() - label->pos();
1306 // Check the number of instructions generated from label to here.
1307 int InstructionsGeneratedSince(Label* label) {
1308 return SizeOfCodeGeneratedSince(label) / kInstrSize;
1311 // Check whether an immediate fits an addressing mode 1 instruction.
1312 bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1314 // Check whether an immediate fits an addressing mode 2 instruction.
1315 bool ImmediateFitsAddrMode2Instruction(int32_t imm32);
1317 // Class for scoping postponing the constant pool generation.
1318 class BlockConstPoolScope {
1320 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1321 assem_->StartBlockConstPool();
1323 ~BlockConstPoolScope() {
1324 assem_->EndBlockConstPool();
1330 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1335 // Mark address of the ExitJSFrame code.
1336 void RecordJSReturn();
1338 // Mark address of a debug break slot.
1339 void RecordDebugBreakSlot();
1341 // Record the AST id of the CallIC being compiled, so that it can be placed
1342 // in the relocation information.
1343 void SetRecordedAstId(TypeFeedbackId ast_id) {
1344 ASSERT(recorded_ast_id_.IsNone());
1345 recorded_ast_id_ = ast_id;
1348 TypeFeedbackId RecordedAstId() {
1349 ASSERT(!recorded_ast_id_.IsNone());
1350 return recorded_ast_id_;
1353 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
1355 // Record a comment relocation entry that can be used by a disassembler.
1356 // Use --code-comments to enable.
1357 void RecordComment(const char* msg);
1359 // Record the emission of a constant pool.
1361 // The emission of constant pool depends on the size of the code generated and
1362 // the number of RelocInfo recorded.
1363 // The Debug mechanism needs to map code offsets between two versions of a
1364 // function, compiled with and without debugger support (see for example
1365 // Debug::PrepareForBreakPoints()).
1366 // Compiling functions with debugger support generates additional code
1367 // (Debug::GenerateSlot()). This may affect the emission of the constant
1368 // pools and cause the version of the code with debugger support to have
1369 // constant pools generated in different places.
1370 // Recording the position and size of emitted constant pools allows to
1371 // correctly compute the offset mappings between the different versions of a
1372 // function in all situations.
1374 // The parameter indicates the size of the constant pool (in bytes), including
1375 // the marker and branch over the data.
1376 void RecordConstPool(int size);
1378 // Writes a single byte or word of data in the code stream. Used
1379 // for inline tables, e.g., jump-tables. The constant pool should be
1380 // emitted before any use of db and dd to ensure that constant pools
1381 // are not emitted as part of the tables generated.
1382 void db(uint8_t data);
1383 void dd(uint32_t data);
1385 // Emits the address of the code stub's first instruction.
1386 void emit_code_stub_address(Code* stub);
1388 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1390 // Read/patch instructions
1391 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1392 void instr_at_put(int pos, Instr instr) {
1393 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1395 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1396 static void instr_at_put(byte* pc, Instr instr) {
1397 *reinterpret_cast<Instr*>(pc) = instr;
1399 static Condition GetCondition(Instr instr);
1400 static bool IsBranch(Instr instr);
1401 static int GetBranchOffset(Instr instr);
1402 static bool IsLdrRegisterImmediate(Instr instr);
1403 static bool IsVldrDRegisterImmediate(Instr instr);
1404 static int GetLdrRegisterImmediateOffset(Instr instr);
1405 static int GetVldrDRegisterImmediateOffset(Instr instr);
1406 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
1407 static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
1408 static bool IsStrRegisterImmediate(Instr instr);
1409 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1410 static bool IsAddRegisterImmediate(Instr instr);
1411 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
1412 static Register GetRd(Instr instr);
1413 static Register GetRn(Instr instr);
1414 static Register GetRm(Instr instr);
1415 static bool IsPush(Instr instr);
1416 static bool IsPop(Instr instr);
1417 static bool IsStrRegFpOffset(Instr instr);
1418 static bool IsLdrRegFpOffset(Instr instr);
1419 static bool IsStrRegFpNegOffset(Instr instr);
1420 static bool IsLdrRegFpNegOffset(Instr instr);
1421 static bool IsLdrPcImmediateOffset(Instr instr);
1422 static bool IsVldrDPcImmediateOffset(Instr instr);
1423 static bool IsTstImmediate(Instr instr);
1424 static bool IsCmpRegister(Instr instr);
1425 static bool IsCmpImmediate(Instr instr);
1426 static Register GetCmpImmediateRegister(Instr instr);
1427 static int GetCmpImmediateRawImmediate(Instr instr);
1428 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1429 static bool IsMovT(Instr instr);
1430 static bool IsMovW(Instr instr);
1432 // Constants in pools are accessed via pc relative addressing, which can
1433 // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
1434 // PC-relative loads, thereby defining a maximum distance between the
1435 // instruction and the accessed constant.
1436 static const int kMaxDistToIntPool = 4*KB;
1437 static const int kMaxDistToFPPool = 1*KB;
1438 // All relocations could be integer, it therefore acts as the limit.
1439 static const int kMaxNumPending32RelocInfo = kMaxDistToIntPool/kInstrSize;
1440 static const int kMaxNumPending64RelocInfo = kMaxDistToFPPool/kInstrSize;
1442 // Postpone the generation of the constant pool for the specified number of
1444 void BlockConstPoolFor(int instructions);
1446 // Check if is time to emit a constant pool.
1447 void CheckConstPool(bool force_emit, bool require_jump);
1450 // Relocation for a type-recording IC has the AST id added to it. This
1451 // member variable is a way to pass the information from the call site to
1452 // the relocation info.
1453 TypeFeedbackId recorded_ast_id_;
1455 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1457 // Decode branch instruction at pos and return branch target pos
1458 int target_at(int pos);
1460 // Patch branch instruction at pos to branch to given branch target pos
1461 void target_at_put(int pos, int target_pos);
1463 // Prevent contant pool emission until EndBlockConstPool is called.
1464 // Call to this function can be nested but must be followed by an equal
1465 // number of call to EndBlockConstpool.
1466 void StartBlockConstPool() {
1467 if (const_pool_blocked_nesting_++ == 0) {
1468 // Prevent constant pool checks happening by setting the next check to
1469 // the biggest possible offset.
1470 next_buffer_check_ = kMaxInt;
1474 // Resume constant pool emission. Need to be called as many time as
1475 // StartBlockConstPool to have an effect.
1476 void EndBlockConstPool() {
1477 if (--const_pool_blocked_nesting_ == 0) {
1479 // Max pool start (if we need a jump and an alignment).
1480 int start = pc_offset() + kInstrSize + 2 * kPointerSize;
1481 // Check the constant pool hasn't been blocked for too long.
1482 ASSERT((num_pending_32_bit_reloc_info_ == 0) ||
1483 (start + num_pending_64_bit_reloc_info_ * kDoubleSize <
1484 (first_const_pool_32_use_ + kMaxDistToIntPool)));
1485 ASSERT((num_pending_64_bit_reloc_info_ == 0) ||
1486 (start < (first_const_pool_64_use_ + kMaxDistToFPPool)));
1489 // * no_const_pool_before_ >= next_buffer_check_ and the emission is
1491 // * no_const_pool_before_ < next_buffer_check_ and the next emit will
1493 next_buffer_check_ = no_const_pool_before_;
1497 bool is_const_pool_blocked() const {
1498 return (const_pool_blocked_nesting_ > 0) ||
1499 (pc_offset() < no_const_pool_before_);
1503 int next_buffer_check_; // pc offset of next buffer check
1506 // The relocation writer's position is at least kGap bytes below the end of
1507 // the generated instructions. This is so that multi-instruction sequences do
1508 // not have to check for overflow. The same is true for writes of large
1509 // relocation info entries.
1510 static const int kGap = 32;
1512 // Constant pool generation
1513 // Pools are emitted in the instruction stream, preferably after unconditional
1514 // jumps or after returns from functions (in dead code locations).
1515 // If a long code sequence does not contain unconditional jumps, it is
1516 // necessary to emit the constant pool before the pool gets too far from the
1517 // location it is accessed from. In this case, we emit a jump over the emitted
1519 // Constants in the pool may be addresses of functions that gets relocated;
1520 // if so, a relocation info entry is associated to the constant pool entry.
1522 // Repeated checking whether the constant pool should be emitted is rather
1523 // expensive. By default we only check again once a number of instructions
1524 // has been generated. That also means that the sizing of the buffers is not
1525 // an exact science, and that we rely on some slop to not overrun buffers.
1526 static const int kCheckPoolIntervalInst = 32;
1527 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
1530 // Emission of the constant pool may be blocked in some code sequences.
1531 int const_pool_blocked_nesting_; // Block emission if this is not zero.
1532 int no_const_pool_before_; // Block emission before this pc offset.
1534 // Keep track of the first instruction requiring a constant pool entry
1535 // since the previous constant pool was emitted.
1536 int first_const_pool_32_use_;
1537 int first_const_pool_64_use_;
1539 // Relocation info generation
1540 // Each relocation is encoded as a variable size value
1541 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1542 RelocInfoWriter reloc_info_writer;
1544 // Relocation info records are also used during code generation as temporary
1545 // containers for constants and code target addresses until they are emitted
1546 // to the constant pool. These pending relocation info records are temporarily
1547 // stored in a separate buffer until a constant pool is emitted.
1548 // If every instruction in a long sequence is accessing the pool, we need one
1549 // pending relocation entry per instruction.
1551 // The buffers of pending relocation info.
1552 RelocInfo pending_32_bit_reloc_info_[kMaxNumPending32RelocInfo];
1553 RelocInfo pending_64_bit_reloc_info_[kMaxNumPending64RelocInfo];
1554 // Number of pending reloc info entries in the 32 bits buffer.
1555 int num_pending_32_bit_reloc_info_;
1556 // Number of pending reloc info entries in the 64 bits buffer.
1557 int num_pending_64_bit_reloc_info_;
1559 // The bound position, before this we cannot do instruction elimination.
1560 int last_bound_pos_;
1563 inline void CheckBuffer();
1565 inline void emit(Instr x);
1567 // 32-bit immediate values
1568 void move_32_bit_immediate(Condition cond,
1573 // Instruction generation
1574 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1575 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1576 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1577 void addrmod4(Instr instr, Register rn, RegList rl);
1578 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1581 void print(Label* L);
1582 void bind_to(Label* L, int pos);
1583 void next(Label* L);
1585 enum UseConstantPoolMode {
1587 DONT_USE_CONSTANT_POOL
1590 // Record reloc info for current pc_
1591 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0,
1592 UseConstantPoolMode mode = USE_CONSTANT_POOL);
1593 void RecordRelocInfo(double data);
1594 void RecordRelocInfoConstantPoolEntryHelper(const RelocInfo& rinfo);
1596 friend class RelocInfo;
1597 friend class CodePatcher;
1598 friend class BlockConstPoolScope;
1600 PositionsRecorder positions_recorder_;
1601 friend class PositionsRecorder;
1602 friend class EnsureSpace;
1606 class EnsureSpace BASE_EMBEDDED {
1608 explicit EnsureSpace(Assembler* assembler) {
1609 assembler->CheckBuffer();
1614 } } // namespace v8::internal
1616 #endif // V8_ARM_ASSEMBLER_ARM_H_