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