Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: src/ppc/assembler-ppc-inl.h

Issue 422063005: Contribution of PowerPC port. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Caught up to bleending edge (8/15) Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. 1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved. 2 // All Rights Reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions 5 // modification, are permitted provided that the following conditions
6 // are met: 6 // are met:
7 // 7 //
8 // - Redistributions of source code must retain the above copyright notice, 8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer. 9 // this list of conditions and the following disclaimer.
10 // 10 //
(...skipping 16 matching lines...) Expand all
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 // OF THE POSSIBILITY OF SUCH DAMAGE. 31 // OF THE POSSIBILITY OF SUCH DAMAGE.
32 32
33 // The original source code covered by the above license above has been modified 33 // The original source code covered by the above license above has been modified
34 // significantly by Google Inc. 34 // significantly by Google Inc.
35 // Copyright 2012 the V8 project authors. All rights reserved. 35 // Copyright 2012 the V8 project authors. All rights reserved.
36 36
37 #ifndef V8_ARM_ASSEMBLER_ARM_INL_H_ 37 //
38 #define V8_ARM_ASSEMBLER_ARM_INL_H_ 38 // Copyright IBM Corp. 2012, 2013. All rights reserved.
39 //
39 40
40 #include "src/arm/assembler-arm.h" 41 #ifndef V8_PPC_ASSEMBLER_PPC_INL_H_
42 #define V8_PPC_ASSEMBLER_PPC_INL_H_
43
44 #include "src/ppc/assembler-ppc.h"
41 45
42 #include "src/assembler.h" 46 #include "src/assembler.h"
43 #include "src/debug.h" 47 #include "src/debug.h"
44 48
45 49
46 namespace v8 { 50 namespace v8 {
47 namespace internal { 51 namespace internal {
48 52
49 53
50 bool CpuFeatures::SupportsCrankshaft() { return IsSupported(VFP3); } 54 bool CpuFeatures::SupportsCrankshaft() { return true; }
51
52
53 int Register::NumAllocatableRegisters() {
54 return kMaxNumAllocatableRegisters;
55 }
56
57
58 int DwVfpRegister::NumRegisters() {
59 return CpuFeatures::IsSupported(VFP32DREGS) ? 32 : 16;
60 }
61
62
63 int DwVfpRegister::NumReservedRegisters() {
64 return kNumReservedRegisters;
65 }
66
67
68 int DwVfpRegister::NumAllocatableRegisters() {
69 return NumRegisters() - kNumReservedRegisters;
70 }
71
72
73 int DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) {
74 DCHECK(!reg.is(kDoubleRegZero));
75 DCHECK(!reg.is(kScratchDoubleReg));
76 if (reg.code() > kDoubleRegZero.code()) {
77 return reg.code() - kNumReservedRegisters;
78 }
79 return reg.code();
80 }
81
82
83 DwVfpRegister DwVfpRegister::FromAllocationIndex(int index) {
84 DCHECK(index >= 0 && index < NumAllocatableRegisters());
85 DCHECK(kScratchDoubleReg.code() - kDoubleRegZero.code() ==
86 kNumReservedRegisters - 1);
87 if (index >= kDoubleRegZero.code()) {
88 return from_code(index + kNumReservedRegisters);
89 }
90 return from_code(index);
91 }
92 55
93 56
94 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) { 57 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) {
58 #if ABI_USES_FUNCTION_DESCRIPTORS || V8_OOL_CONSTANT_POOL
95 if (RelocInfo::IsInternalReference(rmode_)) { 59 if (RelocInfo::IsInternalReference(rmode_)) {
96 // absolute code pointer inside code object moves with the code object. 60 // absolute code pointer inside code object moves with the code object.
97 int32_t* p = reinterpret_cast<int32_t*>(pc_); 61 Assembler::RelocateInternalReference(pc_, delta, 0, icache_flush_mode);
98 *p += delta; // relocate entry
99 } 62 }
100 // We do not use pc relative addressing on ARM, so there is 63 #endif
64 // We do not use pc relative addressing on PPC, so there is
101 // nothing else to do. 65 // nothing else to do.
102 } 66 }
103 67
104 68
105 Address RelocInfo::target_address() { 69 Address RelocInfo::target_address() {
106 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); 70 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
107 return Assembler::target_address_at(pc_, host_); 71 return Assembler::target_address_at(pc_, host_);
108 } 72 }
109 73
110 74
111 Address RelocInfo::target_address_address() { 75 Address RelocInfo::target_address_address() {
112 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) 76 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
113 || rmode_ == EMBEDDED_OBJECT 77 || rmode_ == EMBEDDED_OBJECT
114 || rmode_ == EXTERNAL_REFERENCE); 78 || rmode_ == EXTERNAL_REFERENCE);
115 if (FLAG_enable_ool_constant_pool || 79
116 Assembler::IsMovW(Memory::int32_at(pc_))) { 80 #if V8_OOL_CONSTANT_POOL
81 if (Assembler::IsConstantPoolLoadStart(pc_)) {
117 // We return the PC for ool constant pool since this function is used by the 82 // We return the PC for ool constant pool since this function is used by the
118 // serializerer and expects the address to reside within the code object. 83 // serializerer and expects the address to reside within the code object.
119 return reinterpret_cast<Address>(pc_); 84 return reinterpret_cast<Address>(pc_);
120 } else {
121 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_)));
122 return constant_pool_entry_address();
123 } 85 }
86 #endif
87
88 // Read the address of the word containing the target_address in an
89 // instruction stream.
90 // The only architecture-independent user of this function is the serializer.
91 // The serializer uses it to find out how many raw bytes of instruction to
92 // output before the next target.
93 // For an instruction like LIS/ORI where the target bits are mixed into the
94 // instruction bits, the size of the target will be zero, indicating that the
95 // serializer should not step forward in memory after a target is resolved
96 // and written.
97 return reinterpret_cast<Address>(pc_);
124 } 98 }
125 99
126 100
127 Address RelocInfo::constant_pool_entry_address() { 101 Address RelocInfo::constant_pool_entry_address() {
128 DCHECK(IsInConstantPool()); 102 #if V8_OOL_CONSTANT_POOL
129 return Assembler::constant_pool_entry_address(pc_, host_->constant_pool()); 103 return Assembler::target_constant_pool_address_at(pc_,
104 host_->constant_pool());
105 #else
106 UNREACHABLE();
107 return NULL;
108 #endif
130 } 109 }
131 110
132 111
133 int RelocInfo::target_address_size() { 112 int RelocInfo::target_address_size() {
134 return kPointerSize; 113 return Assembler::kSpecialTargetSize;
135 } 114 }
136 115
137 116
138 void RelocInfo::set_target_address(Address target, 117 void RelocInfo::set_target_address(Address target,
139 WriteBarrierMode write_barrier_mode, 118 WriteBarrierMode write_barrier_mode,
140 ICacheFlushMode icache_flush_mode) { 119 ICacheFlushMode icache_flush_mode) {
141 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); 120 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
142 Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); 121 Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode);
143 if (write_barrier_mode == UPDATE_WRITE_BARRIER && 122 if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
144 host() != NULL && IsCodeTarget(rmode_)) { 123 host() != NULL && IsCodeTarget(rmode_)) {
145 Object* target_code = Code::GetCodeFromTargetAddress(target); 124 Object* target_code = Code::GetCodeFromTargetAddress(target);
146 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( 125 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
147 host(), this, HeapObject::cast(target_code)); 126 host(), this, HeapObject::cast(target_code));
148 } 127 }
149 } 128 }
150 129
151 130
131 Address Assembler::break_address_from_return_address(Address pc) {
132 return target_address_from_return_address(pc);
133 }
134
135
136 Address Assembler::target_address_from_return_address(Address pc) {
137 // Returns the address of the call target from the return address that will
138 // be returned to after a call.
139 // Call sequence is :
140 // mov ip, @ call address
141 // mtlr ip
142 // blrl
143 // @ return address
144 #if V8_OOL_CONSTANT_POOL
145 if (IsConstantPoolLoadEnd(pc - 3 * kInstrSize)) {
146 return pc - (kMovInstructionsConstantPool + 2) * kInstrSize;
147 }
148 #endif
149 return pc - (kMovInstructionsNoConstantPool + 2) * kInstrSize;
150 }
151
152
153 Address Assembler::return_address_from_call_start(Address pc) {
154 #if V8_OOL_CONSTANT_POOL
155 Address load_address = pc + (kMovInstructionsConstantPool - 1) * kInstrSize;
156 if (IsConstantPoolLoadEnd(load_address))
157 return pc + (kMovInstructionsConstantPool + 2) * kInstrSize;
158 #endif
159 return pc + (kMovInstructionsNoConstantPool + 2) * kInstrSize;
160 }
161
162
152 Object* RelocInfo::target_object() { 163 Object* RelocInfo::target_object() {
153 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); 164 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
154 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); 165 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_));
155 } 166 }
156 167
157 168
158 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { 169 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
159 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); 170 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
160 return Handle<Object>(reinterpret_cast<Object**>( 171 return Handle<Object>(reinterpret_cast<Object**>(
161 Assembler::target_address_at(pc_, host_))); 172 Assembler::target_address_at(pc_, host_)));
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 Memory::Address_at(pc_) = address; 231 Memory::Address_at(pc_) = address;
221 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { 232 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) {
222 // TODO(1550) We are passing NULL as a slot because cell can never be on 233 // TODO(1550) We are passing NULL as a slot because cell can never be on
223 // evacuation candidate. 234 // evacuation candidate.
224 host()->GetHeap()->incremental_marking()->RecordWrite( 235 host()->GetHeap()->incremental_marking()->RecordWrite(
225 host(), NULL, cell); 236 host(), NULL, cell);
226 } 237 }
227 } 238 }
228 239
229 240
230 static const int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize; 241 #if V8_OOL_CONSTANT_POOL
242 static const int kNoCodeAgeInstructions = 7;
243 #else
244 static const int kNoCodeAgeInstructions = 6;
245 #endif
246 static const int kCodeAgingInstructions =
247 Assembler::kMovInstructionsNoConstantPool + 3;
248 static const int kNoCodeAgeSequenceInstructions =
249 ((kNoCodeAgeInstructions >= kCodeAgingInstructions) ?
250 kNoCodeAgeInstructions : kCodeAgingInstructions);
251 static const int kNoCodeAgeSequenceNops = (kNoCodeAgeSequenceInstructions -
252 kNoCodeAgeInstructions);
253 static const int kCodeAgingSequenceNops = (kNoCodeAgeSequenceInstructions -
254 kCodeAgingInstructions);
255 static const int kCodeAgingTargetDelta = 1 * Assembler::kInstrSize;
256 static const int kCodeAgingPatchDelta = (kCodeAgingInstructions *
257 Assembler::kInstrSize);
258 static const int kNoCodeAgeSequenceLength = (kNoCodeAgeSequenceInstructions *
259 Assembler::kInstrSize);
231 260
232 261
233 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { 262 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) {
234 UNREACHABLE(); // This should never be reached on Arm. 263 UNREACHABLE(); // This should never be reached on PPC.
235 return Handle<Object>(); 264 return Handle<Object>();
236 } 265 }
237 266
238 267
239 Code* RelocInfo::code_age_stub() { 268 Code* RelocInfo::code_age_stub() {
240 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); 269 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
241 return Code::GetCodeFromTargetAddress( 270 return Code::GetCodeFromTargetAddress(
242 Memory::Address_at(pc_ + 271 Assembler::target_address_at(pc_ + kCodeAgingTargetDelta, host_));
243 (kNoCodeAgeSequenceLength - Assembler::kInstrSize)));
244 } 272 }
245 273
246 274
247 void RelocInfo::set_code_age_stub(Code* stub, 275 void RelocInfo::set_code_age_stub(Code* stub,
248 ICacheFlushMode icache_flush_mode) { 276 ICacheFlushMode icache_flush_mode) {
249 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); 277 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
250 Memory::Address_at(pc_ + 278 Assembler::set_target_address_at(pc_ + kCodeAgingTargetDelta,
251 (kNoCodeAgeSequenceLength - Assembler::kInstrSize)) = 279 host_,
252 stub->instruction_start(); 280 stub->instruction_start(),
281 icache_flush_mode);
253 } 282 }
254 283
255 284
256 Address RelocInfo::call_address() { 285 Address RelocInfo::call_address() {
257 // The 2 instructions offset assumes patched debug break slot or return
258 // sequence.
259 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || 286 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
260 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); 287 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
261 return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize); 288 // The pc_ offset of 0 assumes patched return sequence per
289 // BreakLocationIterator::SetDebugBreakAtReturn(), or debug break
290 // slot per BreakLocationIterator::SetDebugBreakAtSlot().
291 return Assembler::target_address_at(pc_, host_);
262 } 292 }
263 293
264 294
265 void RelocInfo::set_call_address(Address target) { 295 void RelocInfo::set_call_address(Address target) {
266 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || 296 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) ||
267 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); 297 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()));
268 Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; 298 Assembler::set_target_address_at(pc_, host_, target);
269 if (host() != NULL) { 299 if (host() != NULL) {
270 Object* target_code = Code::GetCodeFromTargetAddress(target); 300 Object* target_code = Code::GetCodeFromTargetAddress(target);
271 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( 301 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
272 host(), this, HeapObject::cast(target_code)); 302 host(), this, HeapObject::cast(target_code));
273 } 303 }
274 } 304 }
275 305
276 306
277 Object* RelocInfo::call_object() { 307 Object* RelocInfo::call_object() {
278 return *call_object_address(); 308 return *call_object_address();
(...skipping 15 matching lines...) Expand all
294 void RelocInfo::WipeOut() { 324 void RelocInfo::WipeOut() {
295 DCHECK(IsEmbeddedObject(rmode_) || 325 DCHECK(IsEmbeddedObject(rmode_) ||
296 IsCodeTarget(rmode_) || 326 IsCodeTarget(rmode_) ||
297 IsRuntimeEntry(rmode_) || 327 IsRuntimeEntry(rmode_) ||
298 IsExternalReference(rmode_)); 328 IsExternalReference(rmode_));
299 Assembler::set_target_address_at(pc_, host_, NULL); 329 Assembler::set_target_address_at(pc_, host_, NULL);
300 } 330 }
301 331
302 332
303 bool RelocInfo::IsPatchedReturnSequence() { 333 bool RelocInfo::IsPatchedReturnSequence() {
304 Instr current_instr = Assembler::instr_at(pc_); 334 //
305 Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize); 335 // The patched return sequence is defined by
306 // A patched return sequence is: 336 // BreakLocationIterator::SetDebugBreakAtReturn()
307 // ldr ip, [pc, #0] 337 // FIXED_SEQUENCE
308 // blx ip 338
309 return Assembler::IsLdrPcImmediateOffset(current_instr) && 339 Instr instr0 = Assembler::instr_at(pc_);
310 Assembler::IsBlxReg(next_instr); 340 Instr instr1 = Assembler::instr_at(pc_ + 1 * Assembler::kInstrSize);
341 #if V8_TARGET_ARCH_PPC64
342 Instr instr3 = Assembler::instr_at(pc_ + (3 * Assembler::kInstrSize));
343 Instr instr4 = Assembler::instr_at(pc_ + (4 * Assembler::kInstrSize));
344 Instr binstr = Assembler::instr_at(pc_ + (7 * Assembler::kInstrSize));
345 #else
346 Instr binstr = Assembler::instr_at(pc_ + 4 * Assembler::kInstrSize);
347 #endif
348 bool patched_return = ((instr0 & kOpcodeMask) == ADDIS &&
349 (instr1 & kOpcodeMask) == ORI &&
350 #if V8_TARGET_ARCH_PPC64
351 (instr3 & kOpcodeMask) == ORIS &&
352 (instr4 & kOpcodeMask) == ORI &&
353 #endif
354 (binstr == 0x7d821008)); // twge r2, r2
355
356 // printf("IsPatchedReturnSequence: %d\n", patched_return);
357 return patched_return;
311 } 358 }
312 359
313 360
314 bool RelocInfo::IsPatchedDebugBreakSlotSequence() { 361 bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
315 Instr current_instr = Assembler::instr_at(pc_); 362 Instr current_instr = Assembler::instr_at(pc_);
316 return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP); 363 return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
317 } 364 }
318 365
319 366
320 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) { 367 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
321 RelocInfo::Mode mode = rmode(); 368 RelocInfo::Mode mode = rmode();
322 if (mode == RelocInfo::EMBEDDED_OBJECT) { 369 if (mode == RelocInfo::EMBEDDED_OBJECT) {
323 visitor->VisitEmbeddedPointer(this); 370 visitor->VisitEmbeddedPointer(this);
324 } else if (RelocInfo::IsCodeTarget(mode)) { 371 } else if (RelocInfo::IsCodeTarget(mode)) {
325 visitor->VisitCodeTarget(this); 372 visitor->VisitCodeTarget(this);
326 } else if (mode == RelocInfo::CELL) { 373 } else if (mode == RelocInfo::CELL) {
327 visitor->VisitCell(this); 374 visitor->VisitCell(this);
328 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { 375 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
329 visitor->VisitExternalReference(this); 376 visitor->VisitExternalReference(this);
330 } else if (RelocInfo::IsCodeAgeSequence(mode)) { 377 } else if (RelocInfo::IsCodeAgeSequence(mode)) {
331 visitor->VisitCodeAgeSequence(this); 378 visitor->VisitCodeAgeSequence(this);
332 } else if (((RelocInfo::IsJSReturn(mode) && 379 } else if (((RelocInfo::IsJSReturn(mode) &&
333 IsPatchedReturnSequence()) || 380 IsPatchedReturnSequence()) ||
334 (RelocInfo::IsDebugBreakSlot(mode) && 381 (RelocInfo::IsDebugBreakSlot(mode) &&
335 IsPatchedDebugBreakSlotSequence())) && 382 IsPatchedDebugBreakSlotSequence())) &&
336 isolate->debug()->has_break_points()) { 383 isolate->debug()->has_break_points()) {
337 visitor->VisitDebugTarget(this); 384 visitor->VisitDebugTarget(this);
338 } else if (RelocInfo::IsRuntimeEntry(mode)) { 385 } else if (IsRuntimeEntry(mode)) {
339 visitor->VisitRuntimeEntry(this); 386 visitor->VisitRuntimeEntry(this);
340 } 387 }
341 } 388 }
342 389
343 390
344 template<typename StaticVisitor> 391 template<typename StaticVisitor>
345 void RelocInfo::Visit(Heap* heap) { 392 void RelocInfo::Visit(Heap* heap) {
346 RelocInfo::Mode mode = rmode(); 393 RelocInfo::Mode mode = rmode();
347 if (mode == RelocInfo::EMBEDDED_OBJECT) { 394 if (mode == RelocInfo::EMBEDDED_OBJECT) {
348 StaticVisitor::VisitEmbeddedPointer(heap, this); 395 StaticVisitor::VisitEmbeddedPointer(heap, this);
349 } else if (RelocInfo::IsCodeTarget(mode)) { 396 } else if (RelocInfo::IsCodeTarget(mode)) {
350 StaticVisitor::VisitCodeTarget(heap, this); 397 StaticVisitor::VisitCodeTarget(heap, this);
351 } else if (mode == RelocInfo::CELL) { 398 } else if (mode == RelocInfo::CELL) {
352 StaticVisitor::VisitCell(heap, this); 399 StaticVisitor::VisitCell(heap, this);
353 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { 400 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
354 StaticVisitor::VisitExternalReference(this); 401 StaticVisitor::VisitExternalReference(this);
355 } else if (RelocInfo::IsCodeAgeSequence(mode)) { 402 } else if (RelocInfo::IsCodeAgeSequence(mode)) {
356 StaticVisitor::VisitCodeAgeSequence(heap, this); 403 StaticVisitor::VisitCodeAgeSequence(heap, this);
357 } else if (heap->isolate()->debug()->has_break_points() && 404 } else if (heap->isolate()->debug()->has_break_points() &&
358 ((RelocInfo::IsJSReturn(mode) && 405 ((RelocInfo::IsJSReturn(mode) &&
359 IsPatchedReturnSequence()) || 406 IsPatchedReturnSequence()) ||
360 (RelocInfo::IsDebugBreakSlot(mode) && 407 (RelocInfo::IsDebugBreakSlot(mode) &&
361 IsPatchedDebugBreakSlotSequence()))) { 408 IsPatchedDebugBreakSlotSequence()))) {
362 StaticVisitor::VisitDebugTarget(heap, this); 409 StaticVisitor::VisitDebugTarget(heap, this);
363 } else if (RelocInfo::IsRuntimeEntry(mode)) { 410 } else if (IsRuntimeEntry(mode)) {
364 StaticVisitor::VisitRuntimeEntry(this); 411 StaticVisitor::VisitRuntimeEntry(this);
365 } 412 }
366 } 413 }
367 414
368 415 Operand::Operand(intptr_t immediate, RelocInfo::Mode rmode) {
369 Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) {
370 rm_ = no_reg; 416 rm_ = no_reg;
371 imm32_ = immediate; 417 imm_ = immediate;
372 rmode_ = rmode; 418 rmode_ = rmode;
373 } 419 }
374 420
375
376 Operand::Operand(const ExternalReference& f) { 421 Operand::Operand(const ExternalReference& f) {
377 rm_ = no_reg; 422 rm_ = no_reg;
378 imm32_ = reinterpret_cast<int32_t>(f.address()); 423 imm_ = reinterpret_cast<intptr_t>(f.address());
379 rmode_ = RelocInfo::EXTERNAL_REFERENCE; 424 rmode_ = RelocInfo::EXTERNAL_REFERENCE;
380 } 425 }
381 426
382
383 Operand::Operand(Smi* value) { 427 Operand::Operand(Smi* value) {
384 rm_ = no_reg; 428 rm_ = no_reg;
385 imm32_ = reinterpret_cast<intptr_t>(value); 429 imm_ = reinterpret_cast<intptr_t>(value);
386 rmode_ = RelocInfo::NONE32; 430 rmode_ = kRelocInfo_NONEPTR;
387 } 431 }
388
389 432
390 Operand::Operand(Register rm) { 433 Operand::Operand(Register rm) {
391 rm_ = rm; 434 rm_ = rm;
392 rs_ = no_reg; 435 rmode_ = kRelocInfo_NONEPTR; // PPC -why doesn't ARM do this?
393 shift_op_ = LSL; 436 }
394 shift_imm_ = 0;
395 }
396
397
398 bool Operand::is_reg() const {
399 return rm_.is_valid() &&
400 rs_.is(no_reg) &&
401 shift_op_ == LSL &&
402 shift_imm_ == 0;
403 }
404
405 437
406 void Assembler::CheckBuffer() { 438 void Assembler::CheckBuffer() {
407 if (buffer_space() <= kGap) { 439 if (buffer_space() <= kGap) {
408 GrowBuffer(); 440 GrowBuffer();
409 } 441 }
442 }
443
444 void Assembler::CheckTrampolinePoolQuick() {
410 if (pc_offset() >= next_buffer_check_) { 445 if (pc_offset() >= next_buffer_check_) {
411 CheckConstPool(false, true); 446 CheckTrampolinePool();
412 } 447 }
413 } 448 }
414
415 449
416 void Assembler::emit(Instr x) { 450 void Assembler::emit(Instr x) {
417 CheckBuffer(); 451 CheckBuffer();
418 *reinterpret_cast<Instr*>(pc_) = x; 452 *reinterpret_cast<Instr*>(pc_) = x;
419 pc_ += kInstrSize; 453 pc_ += kInstrSize;
420 } 454 CheckTrampolinePoolQuick();
421 455 }
422 456
423 Address Assembler::target_address_from_return_address(Address pc) { 457 bool Operand::is_reg() const {
424 // Returns the address of the call target from the return address that will 458 return rm_.is_valid();
425 // be returned to after a call. 459 }
426 // Call sequence on V7 or later is : 460
427 // movw ip, #... @ call address low 16 461
428 // movt ip, #... @ call address high 16 462 // Fetch the 32bit value from the FIXED_SEQUENCE lis/ori
429 // blx ip
430 // @ return address
431 // Or pre-V7 or cases that need frequent patching, the address is in the
432 // constant pool. It could be a small constant pool load:
433 // ldr ip, [pc / pp, #...] @ call address
434 // blx ip
435 // @ return address
436 // Or an extended constant pool load:
437 // movw ip, #...
438 // movt ip, #...
439 // ldr ip, [pc, ip] @ call address
440 // blx ip
441 // @ return address
442 Address candidate = pc - 2 * Assembler::kInstrSize;
443 Instr candidate_instr(Memory::int32_at(candidate));
444 if (IsLdrPcImmediateOffset(candidate_instr) |
445 IsLdrPpImmediateOffset(candidate_instr)) {
446 return candidate;
447 } else if (IsLdrPpRegOffset(candidate_instr)) {
448 candidate = pc - 4 * Assembler::kInstrSize;
449 DCHECK(IsMovW(Memory::int32_at(candidate)) &&
450 IsMovT(Memory::int32_at(candidate + Assembler::kInstrSize)));
451 return candidate;
452 } else {
453 candidate = pc - 3 * Assembler::kInstrSize;
454 DCHECK(IsMovW(Memory::int32_at(candidate)) &&
455 IsMovT(Memory::int32_at(candidate + kInstrSize)));
456 return candidate;
457 }
458 }
459
460
461 Address Assembler::break_address_from_return_address(Address pc) {
462 return pc - Assembler::kPatchDebugBreakSlotReturnOffset;
463 }
464
465
466 Address Assembler::return_address_from_call_start(Address pc) {
467 if (IsLdrPcImmediateOffset(Memory::int32_at(pc)) |
468 IsLdrPpImmediateOffset(Memory::int32_at(pc))) {
469 // Load from constant pool, small section.
470 return pc + kInstrSize * 2;
471 } else {
472 DCHECK(IsMovW(Memory::int32_at(pc)));
473 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)));
474 if (IsLdrPpRegOffset(Memory::int32_at(pc + kInstrSize))) {
475 // Load from constant pool, extended section.
476 return pc + kInstrSize * 4;
477 } else {
478 // A movw / movt load immediate.
479 return pc + kInstrSize * 3;
480 }
481 }
482 }
483
484
485 void Assembler::deserialization_set_special_target_at(
486 Address constant_pool_entry, Code* code, Address target) {
487 if (FLAG_enable_ool_constant_pool) {
488 set_target_address_at(constant_pool_entry, code, target);
489 } else {
490 Memory::Address_at(constant_pool_entry) = target;
491 }
492 }
493
494
495 bool Assembler::is_constant_pool_load(Address pc) {
496 return !Assembler::IsMovW(Memory::int32_at(pc)) ||
497 (FLAG_enable_ool_constant_pool &&
498 Assembler::IsLdrPpRegOffset(
499 Memory::int32_at(pc + 2 * Assembler::kInstrSize)));
500 }
501
502
503 Address Assembler::constant_pool_entry_address(
504 Address pc, ConstantPoolArray* constant_pool) {
505 if (FLAG_enable_ool_constant_pool) {
506 DCHECK(constant_pool != NULL);
507 int cp_offset;
508 if (IsMovW(Memory::int32_at(pc))) {
509 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)) &&
510 IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize)));
511 // This is an extended constant pool lookup.
512 Instruction* movw_instr = Instruction::At(pc);
513 Instruction* movt_instr = Instruction::At(pc + kInstrSize);
514 cp_offset = (movt_instr->ImmedMovwMovtValue() << 16) |
515 movw_instr->ImmedMovwMovtValue();
516 } else {
517 // This is a small constant pool lookup.
518 DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc)));
519 cp_offset = GetLdrRegisterImmediateOffset(Memory::int32_at(pc));
520 }
521 return reinterpret_cast<Address>(constant_pool) + cp_offset;
522 } else {
523 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc)));
524 Instr instr = Memory::int32_at(pc);
525 return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta;
526 }
527 }
528
529
530 Address Assembler::target_address_at(Address pc, 463 Address Assembler::target_address_at(Address pc,
531 ConstantPoolArray* constant_pool) { 464 ConstantPoolArray* constant_pool) {
532 if (is_constant_pool_load(pc)) { 465 Instr instr1 = instr_at(pc);
533 // This is a constant pool lookup. Return the value in the constant pool. 466 Instr instr2 = instr_at(pc + kInstrSize);
534 return Memory::Address_at(constant_pool_entry_address(pc, constant_pool)); 467 // Interpret 2 instructions generated by lis/ori
535 } else { 468 if (IsLis(instr1) && IsOri(instr2)) {
536 // This is an movw_movt immediate load. Return the immediate. 469 #if V8_TARGET_ARCH_PPC64
537 DCHECK(IsMovW(Memory::int32_at(pc)) && 470 Instr instr4 = instr_at(pc + (3*kInstrSize));
538 IsMovT(Memory::int32_at(pc + kInstrSize))); 471 Instr instr5 = instr_at(pc + (4*kInstrSize));
539 Instruction* movw_instr = Instruction::At(pc); 472 // Assemble the 64 bit value.
540 Instruction* movt_instr = Instruction::At(pc + kInstrSize); 473 uint64_t hi = (static_cast<uint32_t>((instr1 & kImm16Mask) << 16) |
474 static_cast<uint32_t>(instr2 & kImm16Mask));
475 uint64_t lo = (static_cast<uint32_t>((instr4 & kImm16Mask) << 16) |
476 static_cast<uint32_t>(instr5 & kImm16Mask));
477 return reinterpret_cast<Address>((hi << 32) | lo);
478 #else
479 // Assemble the 32 bit value.
541 return reinterpret_cast<Address>( 480 return reinterpret_cast<Address>(
542 (movt_instr->ImmedMovwMovtValue() << 16) | 481 ((instr1 & kImm16Mask) << 16) | (instr2 & kImm16Mask));
543 movw_instr->ImmedMovwMovtValue()); 482 #endif
544 } 483 }
545 } 484 #if V8_OOL_CONSTANT_POOL
546 485 return Memory::Address_at(
547 486 target_constant_pool_address_at(pc, constant_pool));
487 #else
488 DCHECK(false);
489 return (Address)0;
490 #endif
491 }
492
493
494 #if V8_OOL_CONSTANT_POOL
495 bool Assembler::IsConstantPoolLoadStart(Address pc) {
496 #if V8_TARGET_ARCH_PPC64
497 if (!IsLi(instr_at(pc))) return false;
498 pc += kInstrSize;
499 #endif
500 return GetRA(instr_at(pc)).is(kConstantPoolRegister);
501 }
502
503
504 bool Assembler::IsConstantPoolLoadEnd(Address pc) {
505 #if V8_TARGET_ARCH_PPC64
506 pc -= kInstrSize;
507 #endif
508 return IsConstantPoolLoadStart(pc);
509 }
510
511
512 int Assembler::GetConstantPoolOffset(Address pc) {
513 DCHECK(IsConstantPoolLoadStart(pc));
514 Instr instr = instr_at(pc);
515 int offset = SIGN_EXT_IMM16((instr & kImm16Mask));
516 return offset;
517 }
518
519
520 void Assembler::SetConstantPoolOffset(Address pc, int offset) {
521 DCHECK(IsConstantPoolLoadStart(pc));
522 DCHECK(is_int16(offset));
523 Instr instr = instr_at(pc);
524 instr &= ~kImm16Mask;
525 instr |= (offset & kImm16Mask);
526 instr_at_put(pc, instr);
527 }
528
529
530 Address Assembler::target_constant_pool_address_at(
531 Address pc, ConstantPoolArray* constant_pool) {
532 Address addr = reinterpret_cast<Address>(constant_pool);
533 DCHECK(addr);
534 addr += GetConstantPoolOffset(pc);
535 return addr;
536 }
537 #endif
538
539
540 // This sets the branch destination (which gets loaded at the call address).
541 // This is for calls and branches within generated code. The serializer
542 // has already deserialized the mov instructions etc.
543 // There is a FIXED_SEQUENCE assumption here
544 void Assembler::deserialization_set_special_target_at(
545 Address instruction_payload, Code* code, Address target) {
546 set_target_address_at(instruction_payload, code, target);
547 }
548
549 // This code assumes the FIXED_SEQUENCE of lis/ori
548 void Assembler::set_target_address_at(Address pc, 550 void Assembler::set_target_address_at(Address pc,
549 ConstantPoolArray* constant_pool, 551 ConstantPoolArray* constant_pool,
550 Address target, 552 Address target,
551 ICacheFlushMode icache_flush_mode) { 553 ICacheFlushMode icache_flush_mode) {
552 if (is_constant_pool_load(pc)) { 554 Instr instr1 = instr_at(pc);
553 // This is a constant pool lookup. Update the entry in the constant pool. 555 Instr instr2 = instr_at(pc + kInstrSize);
554 Memory::Address_at(constant_pool_entry_address(pc, constant_pool)) = target; 556 // Interpret 2 instructions generated by lis/ori
555 // Intuitively, we would think it is necessary to always flush the 557 if (IsLis(instr1) && IsOri(instr2)) {
556 // instruction cache after patching a target address in the code as follows: 558 #if V8_TARGET_ARCH_PPC64
557 // CpuFeatures::FlushICache(pc, sizeof(target)); 559 Instr instr4 = instr_at(pc + (3*kInstrSize));
558 // However, on ARM, no instruction is actually patched in the case 560 Instr instr5 = instr_at(pc + (4*kInstrSize));
559 // of embedded constants of the form: 561 // Needs to be fixed up when mov changes to handle 64-bit values.
560 // ldr ip, [pp, #...] 562 uint32_t* p = reinterpret_cast<uint32_t*>(pc);
561 // since the instruction accessing this address in the constant pool remains 563 uintptr_t itarget = reinterpret_cast<uintptr_t>(target);
562 // unchanged. 564
565 instr5 &= ~kImm16Mask;
566 instr5 |= itarget & kImm16Mask;
567 itarget = itarget >> 16;
568
569 instr4 &= ~kImm16Mask;
570 instr4 |= itarget & kImm16Mask;
571 itarget = itarget >> 16;
572
573 instr2 &= ~kImm16Mask;
574 instr2 |= itarget & kImm16Mask;
575 itarget = itarget >> 16;
576
577 instr1 &= ~kImm16Mask;
578 instr1 |= itarget & kImm16Mask;
579 itarget = itarget >> 16;
580
581 *p = instr1;
582 *(p+1) = instr2;
583 *(p+3) = instr4;
584 *(p+4) = instr5;
585 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
586 CpuFeatures::FlushICache(p, 5 * kInstrSize);
587 }
588 #else
589 uint32_t* p = reinterpret_cast<uint32_t*>(pc);
590 uint32_t itarget = reinterpret_cast<uint32_t>(target);
591 int lo_word = itarget & kImm16Mask;
592 int hi_word = itarget >> 16;
593 instr1 &= ~kImm16Mask;
594 instr1 |= hi_word;
595 instr2 &= ~kImm16Mask;
596 instr2 |= lo_word;
597
598 *p = instr1;
599 *(p+1) = instr2;
600 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
601 CpuFeatures::FlushICache(p, 2 * kInstrSize);
602 }
603 #endif
563 } else { 604 } else {
564 // This is an movw_movt immediate load. Patch the immediate embedded in the 605 #if V8_OOL_CONSTANT_POOL
565 // instructions. 606 Memory::Address_at(
566 DCHECK(IsMovW(Memory::int32_at(pc))); 607 target_constant_pool_address_at(pc, constant_pool)) = target;
567 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); 608 #else
568 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc); 609 UNREACHABLE();
569 uint32_t immediate = reinterpret_cast<uint32_t>(target); 610 #endif
570 instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF); 611 }
571 instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16); 612 }
572 DCHECK(IsMovW(Memory::int32_at(pc)));
573 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)));
574 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
575 CpuFeatures::FlushICache(pc, 2 * kInstrSize);
576 }
577 }
578 }
579
580 613
581 } } // namespace v8::internal 614 } } // namespace v8::internal
582 615
583 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ 616 #endif // V8_PPC_ASSEMBLER_PPC_INL_H_
OLDNEW
« src/objects-printer.cc ('K') | « src/ppc/assembler-ppc.cc ('k') | src/ppc/builtins-ppc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698