// Copyright 2013 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/v8.h" #if V8_TARGET_ARCH_ARM64 #include "src/arm64/delayed-masm-arm64.h" #include "src/arm64/lithium-codegen-arm64.h" namespace v8 { namespace internal { #define __ ACCESS_MASM(masm_) void DelayedMasm::StackSlotMove(LOperand* src, LOperand* dst) { DCHECK(src->IsStackSlot()); DCHECK(dst->IsStackSlot()); MemOperand src_operand = cgen_->ToMemOperand(src); MemOperand dst_operand = cgen_->ToMemOperand(dst); if (pending_ == kStackSlotMove) { DCHECK(pending_pc_ == masm_->pc_offset()); UseScratchRegisterScope scope(masm_); DoubleRegister temp1 = scope.AcquireD(); DoubleRegister temp2 = scope.AcquireD(); switch (MemOperand::AreConsistentForPair(pending_address_src_, src_operand)) { case MemOperand::kNotPair: __ Ldr(temp1, pending_address_src_); __ Ldr(temp2, src_operand); break; case MemOperand::kPairAB: __ Ldp(temp1, temp2, pending_address_src_); break; case MemOperand::kPairBA: __ Ldp(temp2, temp1, src_operand); break; } switch (MemOperand::AreConsistentForPair(pending_address_dst_, dst_operand)) { case MemOperand::kNotPair: __ Str(temp1, pending_address_dst_); __ Str(temp2, dst_operand); break; case MemOperand::kPairAB: __ Stp(temp1, temp2, pending_address_dst_); break; case MemOperand::kPairBA: __ Stp(temp2, temp1, dst_operand); break; } ResetPending(); return; } EmitPending(); pending_ = kStackSlotMove; pending_address_src_ = src_operand; pending_address_dst_ = dst_operand; #ifdef DEBUG pending_pc_ = masm_->pc_offset(); #endif } void DelayedMasm::StoreConstant(uint64_t value, const MemOperand& operand) { DCHECK(!scratch_register_acquired_); if ((pending_ == kStoreConstant) && (value == pending_value_)) { MemOperand::PairResult result = MemOperand::AreConsistentForPair(pending_address_dst_, operand); if (result != MemOperand::kNotPair) { const MemOperand& dst = (result == MemOperand::kPairAB) ? pending_address_dst_ : operand; DCHECK(pending_pc_ == masm_->pc_offset()); if (pending_value_ == 0) { __ Stp(xzr, xzr, dst); } else { SetSavedValue(pending_value_); __ Stp(ScratchRegister(), ScratchRegister(), dst); } ResetPending(); return; } } EmitPending(); pending_ = kStoreConstant; pending_address_dst_ = operand; pending_value_ = value; #ifdef DEBUG pending_pc_ = masm_->pc_offset(); #endif } void DelayedMasm::Load(const CPURegister& rd, const MemOperand& operand) { if ((pending_ == kLoad) && pending_register_.IsSameSizeAndType(rd)) { switch (MemOperand::AreConsistentForPair(pending_address_src_, operand)) { case MemOperand::kNotPair: break; case MemOperand::kPairAB: DCHECK(pending_pc_ == masm_->pc_offset()); DCHECK(!IsScratchRegister(pending_register_) || scratch_register_acquired_); DCHECK(!IsScratchRegister(rd) || scratch_register_acquired_); __ Ldp(pending_register_, rd, pending_address_src_); ResetPending(); return; case MemOperand::kPairBA: DCHECK(pending_pc_ == masm_->pc_offset()); DCHECK(!IsScratchRegister(pending_register_) || scratch_register_acquired_); DCHECK(!IsScratchRegister(rd) || scratch_register_acquired_); __ Ldp(rd, pending_register_, operand); ResetPending(); return; } } EmitPending(); pending_ = kLoad; pending_register_ = rd; pending_address_src_ = operand; #ifdef DEBUG pending_pc_ = masm_->pc_offset(); #endif } void DelayedMasm::Store(const CPURegister& rd, const MemOperand& operand) { if ((pending_ == kStore) && pending_register_.IsSameSizeAndType(rd)) { switch (MemOperand::AreConsistentForPair(pending_address_dst_, operand)) { case MemOperand::kNotPair: break; case MemOperand::kPairAB: DCHECK(pending_pc_ == masm_->pc_offset()); __ Stp(pending_register_, rd, pending_address_dst_); ResetPending(); return; case MemOperand::kPairBA: DCHECK(pending_pc_ == masm_->pc_offset()); __ Stp(rd, pending_register_, operand); ResetPending(); return; } } EmitPending(); pending_ = kStore; pending_register_ = rd; pending_address_dst_ = operand; #ifdef DEBUG pending_pc_ = masm_->pc_offset(); #endif } void DelayedMasm::EmitPending() { DCHECK((pending_ == kNone) || (pending_pc_ == masm_->pc_offset())); switch (pending_) { case kNone: return; case kStoreConstant: if (pending_value_ == 0) { __ Str(xzr, pending_address_dst_); } else { SetSavedValue(pending_value_); __ Str(ScratchRegister(), pending_address_dst_); } break; case kLoad: DCHECK(!IsScratchRegister(pending_register_) || scratch_register_acquired_); __ Ldr(pending_register_, pending_address_src_); break; case kStore: __ Str(pending_register_, pending_address_dst_); break; case kStackSlotMove: { UseScratchRegisterScope scope(masm_); DoubleRegister temp = scope.AcquireD(); __ Ldr(temp, pending_address_src_); __ Str(temp, pending_address_dst_); break; } } ResetPending(); } } } // namespace v8::internal #endif // V8_TARGET_ARCH_ARM64