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 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 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 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 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 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