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