Home | History | Annotate | Download | only in arm64
      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