V8 Project
delayed-masm-arm64.cc
Go to the documentation of this file.
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 
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)) {
31  __ Ldr(temp1, pending_address_src_);
32  __ Ldr(temp2, src_operand);
33  break;
35  __ Ldp(temp1, temp2, pending_address_src_);
36  break;
38  __ Ldp(temp2, temp1, src_operand);
39  break;
40  }
41  switch (MemOperand::AreConsistentForPair(pending_address_dst_,
42  dst_operand)) {
44  __ Str(temp1, pending_address_dst_);
45  __ Str(temp2, dst_operand);
46  break;
48  __ Stp(temp1, temp2, pending_address_dst_);
49  break;
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)) {
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)) {
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
static PairResult AreConsistentForPair(const MemOperand &operandA, const MemOperand &operandB, int access_size_log2=kXRegSizeLog2)
#define __
#define DCHECK(condition)
Definition: logging.h:205
DwVfpRegister DoubleRegister
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20