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