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
12namespace v8 {
13namespace internal {
14
15#define __ ACCESS_MASM(masm_)
16
17
18void 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
68void 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
100void 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
135void 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
164void 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