37 #ifndef V8_PPC_ASSEMBLER_PPC_INL_H_ 38 #define V8_PPC_ASSEMBLER_PPC_INL_H_ 40 #include "src/ppc/assembler-ppc.h" 42 #include "src/assembler.h" 43 #include "src/debug/debug.h" 44 #include "src/objects-inl.h" 49 bool CpuFeatures::SupportsOptimizer() {
return true; }
51 bool CpuFeatures::SupportsWasmSimd128() {
return false; }
53 void RelocInfo::apply(intptr_t delta) {
55 if (IsInternalReference(rmode_)) {
57 Address target = Memory<Address>(pc_);
58 Memory<Address>(pc_) = target + delta;
61 DCHECK(IsInternalReferenceEncoded(rmode_));
62 Address target = Assembler::target_address_at(pc_, constant_pool_);
63 Assembler::set_target_address_at(pc_, constant_pool_, target + delta,
69 Address RelocInfo::target_internal_reference() {
70 if (IsInternalReference(rmode_)) {
72 return Memory<Address>(pc_);
75 DCHECK(IsInternalReferenceEncoded(rmode_));
76 return Assembler::target_address_at(pc_, constant_pool_);
81 Address RelocInfo::target_internal_reference_address() {
82 DCHECK(IsInternalReference(rmode_) || IsInternalReferenceEncoded(rmode_));
87 Address RelocInfo::target_address() {
88 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_));
89 return Assembler::target_address_at(pc_, constant_pool_);
92 Address RelocInfo::target_address_address() {
93 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
94 IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
95 IsOffHeapTarget(rmode_));
97 if (FLAG_enable_embedded_constant_pool &&
98 Assembler::IsConstantPoolLoadStart(pc_)) {
118 Address RelocInfo::constant_pool_entry_address() {
119 if (FLAG_enable_embedded_constant_pool) {
120 DCHECK(constant_pool_);
121 ConstantPoolEntry::Access access;
122 if (Assembler::IsConstantPoolLoadStart(pc_, &access))
123 return Assembler::target_constant_pool_address_at(
124 pc_, constant_pool_, access, ConstantPoolEntry::INTPTR);
130 int RelocInfo::target_address_size() {
return Assembler::kSpecialTargetSize; }
132 Address Assembler::target_address_from_return_address(Address pc) {
141 ConstantPoolEntry::Access access;
142 if (FLAG_enable_embedded_constant_pool &&
143 IsConstantPoolLoadEnd(pc - 3 * kInstrSize, &access)) {
144 len = (access == ConstantPoolEntry::OVERFLOWED) ? 2 : 1;
146 len = kMovInstructionsNoConstantPool;
148 return pc - (len + 2) * kInstrSize;
152 Address Assembler::return_address_from_call_start(Address pc) {
154 ConstantPoolEntry::Access access;
155 if (FLAG_enable_embedded_constant_pool &&
156 IsConstantPoolLoadStart(pc, &access)) {
157 len = (access == ConstantPoolEntry::OVERFLOWED) ? 2 : 1;
159 len = kMovInstructionsNoConstantPool;
161 return pc + (len + 2) * kInstrSize;
164 HeapObject* RelocInfo::target_object() {
165 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
166 return HeapObject::cast(reinterpret_cast<Object*>(
167 Assembler::target_address_at(pc_, constant_pool_)));
170 Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
171 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
172 return Handle<HeapObject>(
reinterpret_cast<Address*
>(
173 Assembler::target_address_at(pc_, constant_pool_)));
176 void RelocInfo::set_target_object(Heap* heap, HeapObject* target,
177 WriteBarrierMode write_barrier_mode,
178 ICacheFlushMode icache_flush_mode) {
179 DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
180 Assembler::set_target_address_at(pc_, constant_pool_,
181 reinterpret_cast<Address>(target),
183 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() !=
nullptr) {
184 WriteBarrierForCode(host(),
this, target);
189 Address RelocInfo::target_external_reference() {
190 DCHECK(rmode_ == EXTERNAL_REFERENCE);
191 return Assembler::target_address_at(pc_, constant_pool_);
194 void RelocInfo::set_target_external_reference(
195 Address target, ICacheFlushMode icache_flush_mode) {
196 DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
197 Assembler::set_target_address_at(pc_, constant_pool_, target,
201 Address RelocInfo::target_runtime_entry(Assembler* origin) {
202 DCHECK(IsRuntimeEntry(rmode_));
203 return target_address();
206 void RelocInfo::set_target_runtime_entry(Address target,
207 WriteBarrierMode write_barrier_mode,
208 ICacheFlushMode icache_flush_mode) {
209 DCHECK(IsRuntimeEntry(rmode_));
210 if (target_address() != target)
211 set_target_address(target, write_barrier_mode, icache_flush_mode);
214 Address RelocInfo::target_off_heap_target() {
215 DCHECK(IsOffHeapTarget(rmode_));
216 return Assembler::target_address_at(pc_, constant_pool_);
219 void RelocInfo::WipeOut() {
220 DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
221 IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
222 IsInternalReference(rmode_) || IsInternalReferenceEncoded(rmode_) ||
223 IsOffHeapTarget(rmode_));
224 if (IsInternalReference(rmode_)) {
226 Memory<Address>(pc_) = kNullAddress;
227 }
else if (IsInternalReferenceEncoded(rmode_) || IsOffHeapTarget(rmode_)) {
230 Assembler::set_target_address_at(pc_, constant_pool_, kNullAddress,
233 Assembler::set_target_address_at(pc_, constant_pool_, kNullAddress);
237 template <
typename ObjectVisitor>
238 void RelocInfo::Visit(ObjectVisitor* visitor) {
239 RelocInfo::Mode mode = rmode();
240 if (mode == RelocInfo::EMBEDDED_OBJECT) {
241 visitor->VisitEmbeddedPointer(host(),
this);
242 }
else if (RelocInfo::IsCodeTargetMode(mode)) {
243 visitor->VisitCodeTarget(host(),
this);
244 }
else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
245 visitor->VisitExternalReference(host(),
this);
246 }
else if (mode == RelocInfo::INTERNAL_REFERENCE ||
247 mode == RelocInfo::INTERNAL_REFERENCE_ENCODED) {
248 visitor->VisitInternalReference(host(),
this);
249 }
else if (IsRuntimeEntry(mode)) {
250 visitor->VisitRuntimeEntry(host(),
this);
251 }
else if (RelocInfo::IsOffHeapTarget(mode)) {
252 visitor->VisitOffHeapTarget(host(),
this);
256 Operand::Operand(Register rm) : rm_(rm), rmode_(RelocInfo::NONE) {}
258 void Assembler::UntrackBranch() {
259 DCHECK(!trampoline_emitted_);
260 DCHECK_GT(tracked_branch_count_, 0);
261 int count = --tracked_branch_count_;
264 next_trampoline_check_ = kMaxInt;
266 next_trampoline_check_ += kTrampolineSlotsSize;
271 Address Assembler::target_address_at(Address pc, Address constant_pool) {
272 if (FLAG_enable_embedded_constant_pool && constant_pool) {
273 ConstantPoolEntry::Access access;
274 if (IsConstantPoolLoadStart(pc, &access))
275 return Memory<Address>(target_constant_pool_address_at(
276 pc, constant_pool, access, ConstantPoolEntry::INTPTR));
279 Instr instr1 = instr_at(pc);
280 Instr instr2 = instr_at(pc + kInstrSize);
282 if (IsLis(instr1) && IsOri(instr2)) {
283 #if V8_TARGET_ARCH_PPC64 284 Instr instr4 = instr_at(pc + (3 * kInstrSize));
285 Instr instr5 = instr_at(pc + (4 * kInstrSize));
287 uint64_t hi = (
static_cast<uint32_t>((instr1 & kImm16Mask) << 16) |
288 static_cast<uint32_t>(instr2 & kImm16Mask));
289 uint64_t lo = (
static_cast<uint32_t>((instr4 & kImm16Mask) << 16) |
290 static_cast<uint32_t>(instr5 & kImm16Mask));
291 return static_cast<Address
>((hi << 32) | lo);
294 return static_cast<Address
>(((instr1 & kImm16Mask) << 16) |
295 (instr2 & kImm16Mask));
303 #if V8_TARGET_ARCH_PPC64 304 const uint32_t kLoadIntptrOpcode = LD;
306 const uint32_t kLoadIntptrOpcode = LWZ;
316 bool Assembler::IsConstantPoolLoadStart(Address pc,
317 ConstantPoolEntry::Access* access) {
318 Instr instr = instr_at(pc);
319 uint32_t opcode = instr & kOpcodeMask;
320 if (GetRA(instr) != kConstantPoolRegister)
return false;
321 bool overflowed = (opcode == ADDIS);
324 opcode = instr_at(pc + kInstrSize) & kOpcodeMask;
326 DCHECK(opcode == kLoadIntptrOpcode || opcode == LFD);
329 *access = (overflowed ? ConstantPoolEntry::OVERFLOWED
330 : ConstantPoolEntry::REGULAR);
336 bool Assembler::IsConstantPoolLoadEnd(Address pc,
337 ConstantPoolEntry::Access* access) {
338 Instr instr = instr_at(pc);
339 uint32_t opcode = instr & kOpcodeMask;
340 bool overflowed =
false;
341 if (!(opcode == kLoadIntptrOpcode || opcode == LFD))
return false;
342 if (GetRA(instr) != kConstantPoolRegister) {
343 instr = instr_at(pc - kInstrSize);
344 opcode = instr & kOpcodeMask;
345 if ((opcode != ADDIS) || GetRA(instr) != kConstantPoolRegister) {
351 *access = (overflowed ? ConstantPoolEntry::OVERFLOWED
352 : ConstantPoolEntry::REGULAR);
358 int Assembler::GetConstantPoolOffset(Address pc,
359 ConstantPoolEntry::Access access,
360 ConstantPoolEntry::Type type) {
361 bool overflowed = (access == ConstantPoolEntry::OVERFLOWED);
363 ConstantPoolEntry::Access access_check =
364 static_cast<ConstantPoolEntry::Access
>(-1);
365 DCHECK(IsConstantPoolLoadStart(pc, &access_check));
366 DCHECK(access_check == access);
370 offset = (instr_at(pc) & kImm16Mask) << 16;
371 offset += SIGN_EXT_IMM16(instr_at(pc + kInstrSize) & kImm16Mask);
372 DCHECK(!is_int16(offset));
374 offset = SIGN_EXT_IMM16((instr_at(pc) & kImm16Mask));
380 void Assembler::PatchConstantPoolAccessInstruction(
381 int pc_offset,
int offset, ConstantPoolEntry::Access access,
382 ConstantPoolEntry::Type type) {
383 Address pc =
reinterpret_cast<Address
>(buffer_) + pc_offset;
384 bool overflowed = (access == ConstantPoolEntry::OVERFLOWED);
385 CHECK(overflowed != is_int16(offset));
387 ConstantPoolEntry::Access access_check =
388 static_cast<ConstantPoolEntry::Access
>(-1);
389 DCHECK(IsConstantPoolLoadStart(pc, &access_check));
390 DCHECK(access_check == access);
393 int hi_word =
static_cast<int>(offset >> 16);
394 int lo_word =
static_cast<int>(offset & 0xffff);
395 if (lo_word & 0x8000) hi_word++;
397 Instr instr1 = instr_at(pc);
398 Instr instr2 = instr_at(pc + kInstrSize);
399 instr1 &= ~kImm16Mask;
400 instr1 |= (hi_word & kImm16Mask);
401 instr2 &= ~kImm16Mask;
402 instr2 |= (lo_word & kImm16Mask);
403 instr_at_put(pc, instr1);
404 instr_at_put(pc + kInstrSize, instr2);
406 Instr instr = instr_at(pc);
407 instr &= ~kImm16Mask;
408 instr |= (offset & kImm16Mask);
409 instr_at_put(pc, instr);
414 Address Assembler::target_constant_pool_address_at(
415 Address pc, Address constant_pool, ConstantPoolEntry::Access access,
416 ConstantPoolEntry::Type type) {
417 Address addr = constant_pool;
419 addr += GetConstantPoolOffset(pc, access, type);
428 void Assembler::deserialization_set_special_target_at(
429 Address instruction_payload, Code code, Address target) {
430 set_target_address_at(instruction_payload,
431 code ? code->constant_pool() : kNullAddress, target);
434 int Assembler::deserialization_special_target_size(
435 Address instruction_payload) {
436 return kSpecialTargetSize;
439 void Assembler::deserialization_set_target_internal_reference_at(
440 Address pc, Address target, RelocInfo::Mode mode) {
441 if (RelocInfo::IsInternalReferenceEncoded(mode)) {
442 set_target_address_at(pc, kNullAddress, target, SKIP_ICACHE_FLUSH);
444 Memory<Address>(pc) = target;
450 void Assembler::set_target_address_at(Address pc, Address constant_pool,
452 ICacheFlushMode icache_flush_mode) {
453 if (FLAG_enable_embedded_constant_pool && constant_pool) {
454 ConstantPoolEntry::Access access;
455 if (IsConstantPoolLoadStart(pc, &access)) {
456 Memory<Address>(target_constant_pool_address_at(
457 pc, constant_pool, access, ConstantPoolEntry::INTPTR)) = target;
462 Instr instr1 = instr_at(pc);
463 Instr instr2 = instr_at(pc + kInstrSize);
465 if (IsLis(instr1) && IsOri(instr2)) {
466 #if V8_TARGET_ARCH_PPC64 467 Instr instr4 = instr_at(pc + (3 * kInstrSize));
468 Instr instr5 = instr_at(pc + (4 * kInstrSize));
473 instr5 &= ~kImm16Mask;
474 instr5 |= itarget & kImm16Mask;
475 itarget = itarget >> 16;
477 instr4 &= ~kImm16Mask;
478 instr4 |= itarget & kImm16Mask;
479 itarget = itarget >> 16;
481 instr2 &= ~kImm16Mask;
482 instr2 |= itarget & kImm16Mask;
483 itarget = itarget >> 16;
485 instr1 &= ~kImm16Mask;
486 instr1 |= itarget & kImm16Mask;
487 itarget = itarget >> 16;
493 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
494 Assembler::FlushICache(p, 5 * kInstrSize);
499 int lo_word = itarget & kImm16Mask;
500 int hi_word = itarget >> 16;
501 instr1 &= ~kImm16Mask;
503 instr2 &= ~kImm16Mask;
508 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
509 Assembler::FlushICache(p, 2 * kInstrSize);
519 #endif // V8_PPC_ASSEMBLER_PPC_INL_H_