1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef V8_ARM64_DELAYED_MASM_ARM64_H_
6 #define V8_ARM64_DELAYED_MASM_ARM64_H_
8 #include "src/lithium.h"
15 // This class delays the generation of some instructions. This way, we have a
16 // chance to merge two instructions in one (with load/store pair).
17 // Each instruction must either:
18 // - merge with the pending instruction and generate just one instruction.
19 // - emit the pending instruction and then generate the instruction (or set the
20 // pending instruction).
21 class DelayedMasm BASE_EMBEDDED {
23 DelayedMasm(LCodeGen* owner,
25 const Register& scratch_register)
26 : cgen_(owner), masm_(masm), scratch_register_(scratch_register),
27 scratch_register_used_(false), pending_(kNone), saved_value_(0) {
29 pending_register_ = no_reg;
32 scratch_register_acquired_ = false;
36 DCHECK(!scratch_register_acquired_);
37 DCHECK(!scratch_register_used_);
40 inline void EndDelayedUse();
42 const Register& ScratchRegister() {
43 scratch_register_used_ = true;
44 return scratch_register_;
46 bool IsScratchRegister(const CPURegister& reg) {
47 return reg.Is(scratch_register_);
49 bool scratch_register_used() const { return scratch_register_used_; }
50 void reset_scratch_register_used() { scratch_register_used_ = false; }
51 // Acquire/Release scratch register for use outside this class.
52 void AcquireScratchRegister() {
56 DCHECK(!scratch_register_acquired_);
57 scratch_register_acquired_ = true;
60 void ReleaseScratchRegister() {
62 DCHECK(scratch_register_acquired_);
63 scratch_register_acquired_ = false;
66 bool pending() { return pending_ != kNone; }
68 // Extra layer over the macro-assembler instructions (which emits the
69 // potential pending instruction).
70 inline void Mov(const Register& rd,
71 const Operand& operand,
72 DiscardMoveMode discard_mode = kDontDiscardForSameWReg);
73 inline void Fmov(FPRegister fd, FPRegister fn);
74 inline void Fmov(FPRegister fd, double imm);
75 inline void LoadObject(Register result, Handle<Object> object);
76 // Instructions which try to merge which the pending instructions.
77 void StackSlotMove(LOperand* src, LOperand* dst);
78 // StoreConstant can only be used if the scratch register is not acquired.
79 void StoreConstant(uint64_t value, const MemOperand& operand);
80 void Load(const CPURegister& rd, const MemOperand& operand);
81 void Store(const CPURegister& rd, const MemOperand& operand);
82 // Emit the potential pending instruction.
84 // Reset the pending state.
88 pending_register_ = no_reg;
90 pending_address_src_ = tmp;
91 pending_address_dst_ = tmp;
96 void InitializeRootRegister() {
97 masm_->InitializeRootRegister();
101 // Set the saved value and load the ScratchRegister with it.
102 void SetSavedValue(uint64_t saved_value) {
103 DCHECK(saved_value != 0);
104 if (saved_value_ != saved_value) {
105 masm_->Mov(ScratchRegister(), saved_value);
106 saved_value_ = saved_value;
109 // Reset the saved value (i.e. the value of ScratchRegister is no longer
111 void ResetSavedValue() {
116 MacroAssembler* masm_;
118 // Register used to store a constant.
119 Register scratch_register_;
120 bool scratch_register_used_;
122 // Sometimes we store or load two values in two contiguous stack slots.
123 // In this case, we try to use the ldp/stp instructions to reduce code size.
124 // To be able to do that, instead of generating directly the instructions,
125 // we register with the following fields that an instruction needs to be
126 // generated. Then with the next instruction, if the instruction is
127 // consistent with the pending one for stp/ldp we generate ldp/stp. Else,
128 // if they are not consistent, we generate the pending instruction and we
129 // register the new instruction (which becomes pending).
131 // Enumeration of instructions which can be pending.
138 // The pending instruction.
140 // For kLoad, kStore: register which must be loaded/stored.
141 CPURegister pending_register_;
142 // For kLoad, kStackSlotMove: address of the load.
143 MemOperand pending_address_src_;
144 // For kStoreConstant, kStore, kStackSlotMove: address of the store.
145 MemOperand pending_address_dst_;
146 // For kStoreConstant: value to be stored.
147 uint64_t pending_value_;
148 // Value held into the ScratchRegister if the saved_value_ is not 0.
149 // For 0, we use xzr.
150 uint64_t saved_value_;
152 // Address where the pending instruction must be generated. It's only used to
153 // check that nothing else has been generated since we set the pending
156 // If true, the scratch register has been acquired outside this class. The
157 // scratch register can no longer be used for constants.
158 bool scratch_register_acquired_;
162 } // namespace internal
165 #endif // V8_ARM64_DELAYED_MASM_ARM64_H_