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