• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "src/v8.h"
6 
7 #if V8_TARGET_ARCH_ARM64
8 
9 #include "src/arm64/delayed-masm-arm64.h"
10 #include "src/arm64/lithium-codegen-arm64.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 #define __ ACCESS_MASM(masm_)
16 
17 
StackSlotMove(LOperand * src,LOperand * dst)18 void DelayedMasm::StackSlotMove(LOperand* src, LOperand* dst) {
19   DCHECK(src->IsStackSlot());
20   DCHECK(dst->IsStackSlot());
21   MemOperand src_operand = cgen_->ToMemOperand(src);
22   MemOperand dst_operand = cgen_->ToMemOperand(dst);
23   if (pending_ == kStackSlotMove) {
24     DCHECK(pending_pc_ == masm_->pc_offset());
25     UseScratchRegisterScope scope(masm_);
26     DoubleRegister temp1 = scope.AcquireD();
27     DoubleRegister temp2 = scope.AcquireD();
28     switch (MemOperand::AreConsistentForPair(pending_address_src_,
29                                              src_operand)) {
30       case MemOperand::kNotPair:
31         __ Ldr(temp1, pending_address_src_);
32         __ Ldr(temp2, src_operand);
33         break;
34       case MemOperand::kPairAB:
35         __ Ldp(temp1, temp2, pending_address_src_);
36         break;
37       case MemOperand::kPairBA:
38         __ Ldp(temp2, temp1, src_operand);
39         break;
40     }
41     switch (MemOperand::AreConsistentForPair(pending_address_dst_,
42                                              dst_operand)) {
43       case MemOperand::kNotPair:
44         __ Str(temp1, pending_address_dst_);
45         __ Str(temp2, dst_operand);
46         break;
47       case MemOperand::kPairAB:
48         __ Stp(temp1, temp2, pending_address_dst_);
49         break;
50       case MemOperand::kPairBA:
51         __ Stp(temp2, temp1, dst_operand);
52         break;
53     }
54     ResetPending();
55     return;
56   }
57 
58   EmitPending();
59   pending_ = kStackSlotMove;
60   pending_address_src_ = src_operand;
61   pending_address_dst_ = dst_operand;
62 #ifdef DEBUG
63   pending_pc_ = masm_->pc_offset();
64 #endif
65 }
66 
67 
StoreConstant(uint64_t value,const MemOperand & operand)68 void DelayedMasm::StoreConstant(uint64_t value, const MemOperand& operand) {
69   DCHECK(!scratch_register_acquired_);
70   if ((pending_ == kStoreConstant) && (value == pending_value_)) {
71     MemOperand::PairResult result =
72         MemOperand::AreConsistentForPair(pending_address_dst_, operand);
73     if (result != MemOperand::kNotPair) {
74       const MemOperand& dst =
75           (result == MemOperand::kPairAB) ?
76               pending_address_dst_ :
77               operand;
78       DCHECK(pending_pc_ == masm_->pc_offset());
79       if (pending_value_ == 0) {
80         __ Stp(xzr, xzr, dst);
81       } else {
82         SetSavedValue(pending_value_);
83         __ Stp(ScratchRegister(), ScratchRegister(), dst);
84       }
85       ResetPending();
86       return;
87     }
88   }
89 
90   EmitPending();
91   pending_ = kStoreConstant;
92   pending_address_dst_ = operand;
93   pending_value_ = value;
94 #ifdef DEBUG
95   pending_pc_ = masm_->pc_offset();
96 #endif
97 }
98 
99 
Load(const CPURegister & rd,const MemOperand & operand)100 void DelayedMasm::Load(const CPURegister& rd, const MemOperand& operand) {
101   if ((pending_ == kLoad) &&
102       pending_register_.IsSameSizeAndType(rd)) {
103     switch (MemOperand::AreConsistentForPair(pending_address_src_, operand)) {
104       case MemOperand::kNotPair:
105         break;
106       case MemOperand::kPairAB:
107         DCHECK(pending_pc_ == masm_->pc_offset());
108         DCHECK(!IsScratchRegister(pending_register_) ||
109                scratch_register_acquired_);
110         DCHECK(!IsScratchRegister(rd) || scratch_register_acquired_);
111         __ Ldp(pending_register_, rd, pending_address_src_);
112         ResetPending();
113         return;
114       case MemOperand::kPairBA:
115         DCHECK(pending_pc_ == masm_->pc_offset());
116         DCHECK(!IsScratchRegister(pending_register_) ||
117                scratch_register_acquired_);
118         DCHECK(!IsScratchRegister(rd) || scratch_register_acquired_);
119         __ Ldp(rd, pending_register_, operand);
120         ResetPending();
121         return;
122     }
123   }
124 
125   EmitPending();
126   pending_ = kLoad;
127   pending_register_ = rd;
128   pending_address_src_ = operand;
129 #ifdef DEBUG
130   pending_pc_ = masm_->pc_offset();
131 #endif
132 }
133 
134 
Store(const CPURegister & rd,const MemOperand & operand)135 void DelayedMasm::Store(const CPURegister& rd, const MemOperand& operand) {
136   if ((pending_ == kStore) &&
137       pending_register_.IsSameSizeAndType(rd)) {
138     switch (MemOperand::AreConsistentForPair(pending_address_dst_, operand)) {
139       case MemOperand::kNotPair:
140         break;
141       case MemOperand::kPairAB:
142         DCHECK(pending_pc_ == masm_->pc_offset());
143         __ Stp(pending_register_, rd, pending_address_dst_);
144         ResetPending();
145         return;
146       case MemOperand::kPairBA:
147         DCHECK(pending_pc_ == masm_->pc_offset());
148         __ Stp(rd, pending_register_, operand);
149         ResetPending();
150         return;
151     }
152   }
153 
154   EmitPending();
155   pending_ = kStore;
156   pending_register_ = rd;
157   pending_address_dst_ = operand;
158 #ifdef DEBUG
159   pending_pc_ = masm_->pc_offset();
160 #endif
161 }
162 
163 
EmitPending()164 void DelayedMasm::EmitPending() {
165   DCHECK((pending_ == kNone) || (pending_pc_ == masm_->pc_offset()));
166   switch (pending_) {
167     case kNone:
168       return;
169     case kStoreConstant:
170       if (pending_value_ == 0) {
171         __ Str(xzr, pending_address_dst_);
172       } else {
173         SetSavedValue(pending_value_);
174         __ Str(ScratchRegister(), pending_address_dst_);
175       }
176       break;
177     case kLoad:
178       DCHECK(!IsScratchRegister(pending_register_) ||
179               scratch_register_acquired_);
180       __ Ldr(pending_register_, pending_address_src_);
181       break;
182     case kStore:
183       __ Str(pending_register_, pending_address_dst_);
184       break;
185     case kStackSlotMove: {
186       UseScratchRegisterScope scope(masm_);
187       DoubleRegister temp = scope.AcquireD();
188       __ Ldr(temp, pending_address_src_);
189       __ Str(temp, pending_address_dst_);
190       break;
191     }
192   }
193   ResetPending();
194 }
195 
196 } }  // namespace v8::internal
197 
198 #endif  // V8_TARGET_ARCH_ARM64
199