11cb0ef41Sopenharmony_ci// Copyright (c) 1994-2006 Sun Microsystems Inc. 21cb0ef41Sopenharmony_ci// All Rights Reserved. 31cb0ef41Sopenharmony_ci// 41cb0ef41Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 51cb0ef41Sopenharmony_ci// modification, are permitted provided that the following conditions 61cb0ef41Sopenharmony_ci// are met: 71cb0ef41Sopenharmony_ci// 81cb0ef41Sopenharmony_ci// - Redistributions of source code must retain the above copyright notice, 91cb0ef41Sopenharmony_ci// this list of conditions and the following disclaimer. 101cb0ef41Sopenharmony_ci// 111cb0ef41Sopenharmony_ci// - Redistribution in binary form must reproduce the above copyright 121cb0ef41Sopenharmony_ci// notice, this list of conditions and the following disclaimer in the 131cb0ef41Sopenharmony_ci// documentation and/or other materials provided with the 141cb0ef41Sopenharmony_ci// distribution. 151cb0ef41Sopenharmony_ci// 161cb0ef41Sopenharmony_ci// - Neither the name of Sun Microsystems or the names of contributors may 171cb0ef41Sopenharmony_ci// be used to endorse or promote products derived from this software without 181cb0ef41Sopenharmony_ci// specific prior written permission. 191cb0ef41Sopenharmony_ci// 201cb0ef41Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 211cb0ef41Sopenharmony_ci// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 221cb0ef41Sopenharmony_ci// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 231cb0ef41Sopenharmony_ci// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 241cb0ef41Sopenharmony_ci// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 251cb0ef41Sopenharmony_ci// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 261cb0ef41Sopenharmony_ci// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 271cb0ef41Sopenharmony_ci// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281cb0ef41Sopenharmony_ci// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 291cb0ef41Sopenharmony_ci// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 301cb0ef41Sopenharmony_ci// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 311cb0ef41Sopenharmony_ci// OF THE POSSIBILITY OF SUCH DAMAGE. 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci// The original source code covered by the above license above has been modified 341cb0ef41Sopenharmony_ci// significantly by Google Inc. 351cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci#ifndef V8_CODEGEN_PPC_ASSEMBLER_PPC_INL_H_ 381cb0ef41Sopenharmony_ci#define V8_CODEGEN_PPC_ASSEMBLER_PPC_INL_H_ 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci#include "src/codegen/ppc/assembler-ppc.h" 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci#include "src/codegen/assembler.h" 431cb0ef41Sopenharmony_ci#include "src/debug/debug.h" 441cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_cinamespace v8 { 471cb0ef41Sopenharmony_cinamespace internal { 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_cibool CpuFeatures::SupportsOptimizer() { return true; } 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_civoid RelocInfo::apply(intptr_t delta) { 521cb0ef41Sopenharmony_ci // absolute code pointer inside code object moves with the code object. 531cb0ef41Sopenharmony_ci if (IsInternalReference(rmode_)) { 541cb0ef41Sopenharmony_ci // Jump table entry 551cb0ef41Sopenharmony_ci Address target = Memory<Address>(pc_); 561cb0ef41Sopenharmony_ci Memory<Address>(pc_) = target + delta; 571cb0ef41Sopenharmony_ci } else { 581cb0ef41Sopenharmony_ci // mov sequence 591cb0ef41Sopenharmony_ci DCHECK(IsInternalReferenceEncoded(rmode_)); 601cb0ef41Sopenharmony_ci Address target = Assembler::target_address_at(pc_, constant_pool_); 611cb0ef41Sopenharmony_ci Assembler::set_target_address_at(pc_, constant_pool_, target + delta, 621cb0ef41Sopenharmony_ci SKIP_ICACHE_FLUSH); 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci} 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ciAddress RelocInfo::target_internal_reference() { 671cb0ef41Sopenharmony_ci if (IsInternalReference(rmode_)) { 681cb0ef41Sopenharmony_ci // Jump table entry 691cb0ef41Sopenharmony_ci return Memory<Address>(pc_); 701cb0ef41Sopenharmony_ci } else { 711cb0ef41Sopenharmony_ci // mov sequence 721cb0ef41Sopenharmony_ci DCHECK(IsInternalReferenceEncoded(rmode_)); 731cb0ef41Sopenharmony_ci return Assembler::target_address_at(pc_, constant_pool_); 741cb0ef41Sopenharmony_ci } 751cb0ef41Sopenharmony_ci} 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ciAddress RelocInfo::target_internal_reference_address() { 781cb0ef41Sopenharmony_ci DCHECK(IsInternalReference(rmode_) || IsInternalReferenceEncoded(rmode_)); 791cb0ef41Sopenharmony_ci return pc_; 801cb0ef41Sopenharmony_ci} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ciAddress RelocInfo::target_address() { 831cb0ef41Sopenharmony_ci DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_)); 841cb0ef41Sopenharmony_ci return Assembler::target_address_at(pc_, constant_pool_); 851cb0ef41Sopenharmony_ci} 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ciAddress RelocInfo::target_address_address() { 881cb0ef41Sopenharmony_ci DCHECK(HasTargetAddressAddress()); 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci if (FLAG_enable_embedded_constant_pool && 911cb0ef41Sopenharmony_ci Assembler::IsConstantPoolLoadStart(pc_)) { 921cb0ef41Sopenharmony_ci // We return the PC for embedded constant pool since this function is used 931cb0ef41Sopenharmony_ci // by the serializer and expects the address to reside within the code 941cb0ef41Sopenharmony_ci // object. 951cb0ef41Sopenharmony_ci return pc_; 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci // Read the address of the word containing the target_address in an 991cb0ef41Sopenharmony_ci // instruction stream. 1001cb0ef41Sopenharmony_ci // The only architecture-independent user of this function is the serializer. 1011cb0ef41Sopenharmony_ci // The serializer uses it to find out how many raw bytes of instruction to 1021cb0ef41Sopenharmony_ci // output before the next target. 1031cb0ef41Sopenharmony_ci // For an instruction like LIS/ORI where the target bits are mixed into the 1041cb0ef41Sopenharmony_ci // instruction bits, the size of the target will be zero, indicating that the 1051cb0ef41Sopenharmony_ci // serializer should not step forward in memory after a target is resolved 1061cb0ef41Sopenharmony_ci // and written. 1071cb0ef41Sopenharmony_ci return pc_; 1081cb0ef41Sopenharmony_ci} 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ciAddress RelocInfo::constant_pool_entry_address() { 1111cb0ef41Sopenharmony_ci if (FLAG_enable_embedded_constant_pool) { 1121cb0ef41Sopenharmony_ci DCHECK(constant_pool_); 1131cb0ef41Sopenharmony_ci ConstantPoolEntry::Access access; 1141cb0ef41Sopenharmony_ci if (Assembler::IsConstantPoolLoadStart(pc_, &access)) 1151cb0ef41Sopenharmony_ci return Assembler::target_constant_pool_address_at( 1161cb0ef41Sopenharmony_ci pc_, constant_pool_, access, ConstantPoolEntry::INTPTR); 1171cb0ef41Sopenharmony_ci } 1181cb0ef41Sopenharmony_ci UNREACHABLE(); 1191cb0ef41Sopenharmony_ci} 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_civoid Assembler::set_target_compressed_address_at( 1221cb0ef41Sopenharmony_ci Address pc, Address constant_pool, Tagged_t target, 1231cb0ef41Sopenharmony_ci ICacheFlushMode icache_flush_mode) { 1241cb0ef41Sopenharmony_ci Assembler::set_target_address_at( 1251cb0ef41Sopenharmony_ci pc, constant_pool, static_cast<Address>(target), icache_flush_mode); 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ciint RelocInfo::target_address_size() { 1291cb0ef41Sopenharmony_ci if (IsCodedSpecially()) { 1301cb0ef41Sopenharmony_ci return Assembler::kSpecialTargetSize; 1311cb0ef41Sopenharmony_ci } else { 1321cb0ef41Sopenharmony_ci return kSystemPointerSize; 1331cb0ef41Sopenharmony_ci } 1341cb0ef41Sopenharmony_ci} 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ciTagged_t Assembler::target_compressed_address_at(Address pc, 1371cb0ef41Sopenharmony_ci Address constant_pool) { 1381cb0ef41Sopenharmony_ci return static_cast<Tagged_t>(target_address_at(pc, constant_pool)); 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ciHandle<Object> Assembler::code_target_object_handle_at(Address pc, 1421cb0ef41Sopenharmony_ci Address constant_pool) { 1431cb0ef41Sopenharmony_ci int index = 1441cb0ef41Sopenharmony_ci static_cast<int>(target_address_at(pc, constant_pool)) & 0xFFFFFFFF; 1451cb0ef41Sopenharmony_ci return GetCodeTarget(index); 1461cb0ef41Sopenharmony_ci} 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ciHeapObject RelocInfo::target_object(PtrComprCageBase cage_base) { 1491cb0ef41Sopenharmony_ci DCHECK(IsCodeTarget(rmode_) || IsEmbeddedObjectMode(rmode_)); 1501cb0ef41Sopenharmony_ci if (IsDataEmbeddedObject(rmode_)) { 1511cb0ef41Sopenharmony_ci return HeapObject::cast(Object(ReadUnalignedValue<Address>(pc_))); 1521cb0ef41Sopenharmony_ci } else if (IsCompressedEmbeddedObject(rmode_)) { 1531cb0ef41Sopenharmony_ci return HeapObject::cast(Object(DecompressTaggedAny( 1541cb0ef41Sopenharmony_ci cage_base, 1551cb0ef41Sopenharmony_ci Assembler::target_compressed_address_at(pc_, constant_pool_)))); 1561cb0ef41Sopenharmony_ci } else { 1571cb0ef41Sopenharmony_ci return HeapObject::cast( 1581cb0ef41Sopenharmony_ci Object(Assembler::target_address_at(pc_, constant_pool_))); 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci} 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ciHandle<HeapObject> Assembler::compressed_embedded_object_handle_at( 1631cb0ef41Sopenharmony_ci Address pc, Address const_pool) { 1641cb0ef41Sopenharmony_ci return GetEmbeddedObject(target_compressed_address_at(pc, const_pool)); 1651cb0ef41Sopenharmony_ci} 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ciHandle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) { 1681cb0ef41Sopenharmony_ci DCHECK(IsCodeTarget(rmode_) || IsEmbeddedObjectMode(rmode_)); 1691cb0ef41Sopenharmony_ci if (IsDataEmbeddedObject(rmode_)) { 1701cb0ef41Sopenharmony_ci return Handle<HeapObject>::cast(ReadUnalignedValue<Handle<Object>>(pc_)); 1711cb0ef41Sopenharmony_ci } else if (IsCodeTarget(rmode_)) { 1721cb0ef41Sopenharmony_ci return Handle<HeapObject>::cast( 1731cb0ef41Sopenharmony_ci origin->code_target_object_handle_at(pc_, constant_pool_)); 1741cb0ef41Sopenharmony_ci } else { 1751cb0ef41Sopenharmony_ci if (IsCompressedEmbeddedObject(rmode_)) { 1761cb0ef41Sopenharmony_ci return origin->compressed_embedded_object_handle_at(pc_, constant_pool_); 1771cb0ef41Sopenharmony_ci } 1781cb0ef41Sopenharmony_ci return Handle<HeapObject>(reinterpret_cast<Address*>( 1791cb0ef41Sopenharmony_ci Assembler::target_address_at(pc_, constant_pool_))); 1801cb0ef41Sopenharmony_ci } 1811cb0ef41Sopenharmony_ci} 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_civoid RelocInfo::set_target_object(Heap* heap, HeapObject target, 1841cb0ef41Sopenharmony_ci WriteBarrierMode write_barrier_mode, 1851cb0ef41Sopenharmony_ci ICacheFlushMode icache_flush_mode) { 1861cb0ef41Sopenharmony_ci DCHECK(IsCodeTarget(rmode_) || IsEmbeddedObjectMode(rmode_)); 1871cb0ef41Sopenharmony_ci if (IsDataEmbeddedObject(rmode_)) { 1881cb0ef41Sopenharmony_ci WriteUnalignedValue(pc_, target.ptr()); 1891cb0ef41Sopenharmony_ci // No need to flush icache since no instructions were changed. 1901cb0ef41Sopenharmony_ci } else if (IsCompressedEmbeddedObject(rmode_)) { 1911cb0ef41Sopenharmony_ci Assembler::set_target_compressed_address_at( 1921cb0ef41Sopenharmony_ci pc_, constant_pool_, CompressTagged(target.ptr()), icache_flush_mode); 1931cb0ef41Sopenharmony_ci } else { 1941cb0ef41Sopenharmony_ci DCHECK(IsFullEmbeddedObject(rmode_)); 1951cb0ef41Sopenharmony_ci Assembler::set_target_address_at(pc_, constant_pool_, target.ptr(), 1961cb0ef41Sopenharmony_ci icache_flush_mode); 1971cb0ef41Sopenharmony_ci } 1981cb0ef41Sopenharmony_ci if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() && 1991cb0ef41Sopenharmony_ci !FLAG_disable_write_barriers) { 2001cb0ef41Sopenharmony_ci WriteBarrierForCode(host(), this, target); 2011cb0ef41Sopenharmony_ci } 2021cb0ef41Sopenharmony_ci} 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ciAddress RelocInfo::target_external_reference() { 2051cb0ef41Sopenharmony_ci DCHECK(rmode_ == EXTERNAL_REFERENCE); 2061cb0ef41Sopenharmony_ci return Assembler::target_address_at(pc_, constant_pool_); 2071cb0ef41Sopenharmony_ci} 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_civoid RelocInfo::set_target_external_reference( 2101cb0ef41Sopenharmony_ci Address target, ICacheFlushMode icache_flush_mode) { 2111cb0ef41Sopenharmony_ci DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE); 2121cb0ef41Sopenharmony_ci Assembler::set_target_address_at(pc_, constant_pool_, target, 2131cb0ef41Sopenharmony_ci icache_flush_mode); 2141cb0ef41Sopenharmony_ci} 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ciAddress RelocInfo::target_runtime_entry(Assembler* origin) { 2171cb0ef41Sopenharmony_ci DCHECK(IsRuntimeEntry(rmode_)); 2181cb0ef41Sopenharmony_ci return target_address(); 2191cb0ef41Sopenharmony_ci} 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_civoid RelocInfo::set_target_runtime_entry(Address target, 2221cb0ef41Sopenharmony_ci WriteBarrierMode write_barrier_mode, 2231cb0ef41Sopenharmony_ci ICacheFlushMode icache_flush_mode) { 2241cb0ef41Sopenharmony_ci DCHECK(IsRuntimeEntry(rmode_)); 2251cb0ef41Sopenharmony_ci if (target_address() != target) 2261cb0ef41Sopenharmony_ci set_target_address(target, write_barrier_mode, icache_flush_mode); 2271cb0ef41Sopenharmony_ci} 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ciAddress RelocInfo::target_off_heap_target() { 2301cb0ef41Sopenharmony_ci DCHECK(IsOffHeapTarget(rmode_)); 2311cb0ef41Sopenharmony_ci return Assembler::target_address_at(pc_, constant_pool_); 2321cb0ef41Sopenharmony_ci} 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_civoid RelocInfo::WipeOut() { 2351cb0ef41Sopenharmony_ci DCHECK(IsEmbeddedObjectMode(rmode_) || IsCodeTarget(rmode_) || 2361cb0ef41Sopenharmony_ci IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) || 2371cb0ef41Sopenharmony_ci IsInternalReference(rmode_) || IsInternalReferenceEncoded(rmode_) || 2381cb0ef41Sopenharmony_ci IsOffHeapTarget(rmode_)); 2391cb0ef41Sopenharmony_ci if (IsInternalReference(rmode_)) { 2401cb0ef41Sopenharmony_ci // Jump table entry 2411cb0ef41Sopenharmony_ci Memory<Address>(pc_) = kNullAddress; 2421cb0ef41Sopenharmony_ci } else if (IsCompressedEmbeddedObject(rmode_)) { 2431cb0ef41Sopenharmony_ci Assembler::set_target_compressed_address_at(pc_, constant_pool_, 2441cb0ef41Sopenharmony_ci kNullAddress); 2451cb0ef41Sopenharmony_ci } else if (IsInternalReferenceEncoded(rmode_) || IsOffHeapTarget(rmode_)) { 2461cb0ef41Sopenharmony_ci // mov sequence 2471cb0ef41Sopenharmony_ci // Currently used only by deserializer, no need to flush. 2481cb0ef41Sopenharmony_ci Assembler::set_target_address_at(pc_, constant_pool_, kNullAddress, 2491cb0ef41Sopenharmony_ci SKIP_ICACHE_FLUSH); 2501cb0ef41Sopenharmony_ci } else { 2511cb0ef41Sopenharmony_ci Assembler::set_target_address_at(pc_, constant_pool_, kNullAddress); 2521cb0ef41Sopenharmony_ci } 2531cb0ef41Sopenharmony_ci} 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ciOperand::Operand(Register rm) : rm_(rm), rmode_(RelocInfo::NO_INFO) {} 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_civoid Assembler::UntrackBranch() { 2581cb0ef41Sopenharmony_ci DCHECK(!trampoline_emitted_); 2591cb0ef41Sopenharmony_ci DCHECK_GT(tracked_branch_count_, 0); 2601cb0ef41Sopenharmony_ci int count = --tracked_branch_count_; 2611cb0ef41Sopenharmony_ci if (count == 0) { 2621cb0ef41Sopenharmony_ci // Reset 2631cb0ef41Sopenharmony_ci next_trampoline_check_ = kMaxInt; 2641cb0ef41Sopenharmony_ci } else { 2651cb0ef41Sopenharmony_ci next_trampoline_check_ += kTrampolineSlotsSize; 2661cb0ef41Sopenharmony_ci } 2671cb0ef41Sopenharmony_ci} 2681cb0ef41Sopenharmony_ci 2691cb0ef41Sopenharmony_ci// Fetch the 32bit value from the FIXED_SEQUENCE lis/ori 2701cb0ef41Sopenharmony_ciAddress Assembler::target_address_at(Address pc, Address constant_pool) { 2711cb0ef41Sopenharmony_ci if (FLAG_enable_embedded_constant_pool && constant_pool) { 2721cb0ef41Sopenharmony_ci ConstantPoolEntry::Access access; 2731cb0ef41Sopenharmony_ci if (IsConstantPoolLoadStart(pc, &access)) 2741cb0ef41Sopenharmony_ci return Memory<Address>(target_constant_pool_address_at( 2751cb0ef41Sopenharmony_ci pc, constant_pool, access, ConstantPoolEntry::INTPTR)); 2761cb0ef41Sopenharmony_ci } 2771cb0ef41Sopenharmony_ci 2781cb0ef41Sopenharmony_ci Instr instr1 = instr_at(pc); 2791cb0ef41Sopenharmony_ci Instr instr2 = instr_at(pc + kInstrSize); 2801cb0ef41Sopenharmony_ci // Interpret 2 instructions generated by lis/ori 2811cb0ef41Sopenharmony_ci if (IsLis(instr1) && IsOri(instr2)) { 2821cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_PPC64 2831cb0ef41Sopenharmony_ci Instr instr4 = instr_at(pc + (3 * kInstrSize)); 2841cb0ef41Sopenharmony_ci Instr instr5 = instr_at(pc + (4 * kInstrSize)); 2851cb0ef41Sopenharmony_ci // Assemble the 64 bit value. 2861cb0ef41Sopenharmony_ci uint64_t hi = (static_cast<uint32_t>((instr1 & kImm16Mask) << 16) | 2871cb0ef41Sopenharmony_ci static_cast<uint32_t>(instr2 & kImm16Mask)); 2881cb0ef41Sopenharmony_ci uint64_t lo = (static_cast<uint32_t>((instr4 & kImm16Mask) << 16) | 2891cb0ef41Sopenharmony_ci static_cast<uint32_t>(instr5 & kImm16Mask)); 2901cb0ef41Sopenharmony_ci return static_cast<Address>((hi << 32) | lo); 2911cb0ef41Sopenharmony_ci#else 2921cb0ef41Sopenharmony_ci // Assemble the 32 bit value. 2931cb0ef41Sopenharmony_ci return static_cast<Address>(((instr1 & kImm16Mask) << 16) | 2941cb0ef41Sopenharmony_ci (instr2 & kImm16Mask)); 2951cb0ef41Sopenharmony_ci#endif 2961cb0ef41Sopenharmony_ci } 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci UNREACHABLE(); 2991cb0ef41Sopenharmony_ci} 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_PPC64 3021cb0ef41Sopenharmony_ciconst uint32_t kLoadIntptrOpcode = LD; 3031cb0ef41Sopenharmony_ci#else 3041cb0ef41Sopenharmony_ciconst uint32_t kLoadIntptrOpcode = LWZ; 3051cb0ef41Sopenharmony_ci#endif 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci// Constant pool load sequence detection: 3081cb0ef41Sopenharmony_ci// 1) REGULAR access: 3091cb0ef41Sopenharmony_ci// load <dst>, kConstantPoolRegister + <offset> 3101cb0ef41Sopenharmony_ci// 3111cb0ef41Sopenharmony_ci// 2) OVERFLOWED access: 3121cb0ef41Sopenharmony_ci// addis <scratch>, kConstantPoolRegister, <offset_high> 3131cb0ef41Sopenharmony_ci// load <dst>, <scratch> + <offset_low> 3141cb0ef41Sopenharmony_cibool Assembler::IsConstantPoolLoadStart(Address pc, 3151cb0ef41Sopenharmony_ci ConstantPoolEntry::Access* access) { 3161cb0ef41Sopenharmony_ci Instr instr = instr_at(pc); 3171cb0ef41Sopenharmony_ci uint32_t opcode = instr & kOpcodeMask; 3181cb0ef41Sopenharmony_ci if (GetRA(instr) != kConstantPoolRegister) return false; 3191cb0ef41Sopenharmony_ci bool overflowed = (opcode == ADDIS); 3201cb0ef41Sopenharmony_ci#ifdef DEBUG 3211cb0ef41Sopenharmony_ci if (overflowed) { 3221cb0ef41Sopenharmony_ci opcode = instr_at(pc + kInstrSize) & kOpcodeMask; 3231cb0ef41Sopenharmony_ci } 3241cb0ef41Sopenharmony_ci DCHECK(opcode == kLoadIntptrOpcode || opcode == LFD); 3251cb0ef41Sopenharmony_ci#endif 3261cb0ef41Sopenharmony_ci if (access) { 3271cb0ef41Sopenharmony_ci *access = (overflowed ? ConstantPoolEntry::OVERFLOWED 3281cb0ef41Sopenharmony_ci : ConstantPoolEntry::REGULAR); 3291cb0ef41Sopenharmony_ci } 3301cb0ef41Sopenharmony_ci return true; 3311cb0ef41Sopenharmony_ci} 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_cibool Assembler::IsConstantPoolLoadEnd(Address pc, 3341cb0ef41Sopenharmony_ci ConstantPoolEntry::Access* access) { 3351cb0ef41Sopenharmony_ci Instr instr = instr_at(pc); 3361cb0ef41Sopenharmony_ci uint32_t opcode = instr & kOpcodeMask; 3371cb0ef41Sopenharmony_ci bool overflowed = false; 3381cb0ef41Sopenharmony_ci if (!(opcode == kLoadIntptrOpcode || opcode == LFD)) return false; 3391cb0ef41Sopenharmony_ci if (GetRA(instr) != kConstantPoolRegister) { 3401cb0ef41Sopenharmony_ci instr = instr_at(pc - kInstrSize); 3411cb0ef41Sopenharmony_ci opcode = instr & kOpcodeMask; 3421cb0ef41Sopenharmony_ci if ((opcode != ADDIS) || GetRA(instr) != kConstantPoolRegister) { 3431cb0ef41Sopenharmony_ci return false; 3441cb0ef41Sopenharmony_ci } 3451cb0ef41Sopenharmony_ci overflowed = true; 3461cb0ef41Sopenharmony_ci } 3471cb0ef41Sopenharmony_ci if (access) { 3481cb0ef41Sopenharmony_ci *access = (overflowed ? ConstantPoolEntry::OVERFLOWED 3491cb0ef41Sopenharmony_ci : ConstantPoolEntry::REGULAR); 3501cb0ef41Sopenharmony_ci } 3511cb0ef41Sopenharmony_ci return true; 3521cb0ef41Sopenharmony_ci} 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ciint Assembler::GetConstantPoolOffset(Address pc, 3551cb0ef41Sopenharmony_ci ConstantPoolEntry::Access access, 3561cb0ef41Sopenharmony_ci ConstantPoolEntry::Type type) { 3571cb0ef41Sopenharmony_ci bool overflowed = (access == ConstantPoolEntry::OVERFLOWED); 3581cb0ef41Sopenharmony_ci#ifdef DEBUG 3591cb0ef41Sopenharmony_ci ConstantPoolEntry::Access access_check = 3601cb0ef41Sopenharmony_ci static_cast<ConstantPoolEntry::Access>(-1); 3611cb0ef41Sopenharmony_ci DCHECK(IsConstantPoolLoadStart(pc, &access_check)); 3621cb0ef41Sopenharmony_ci DCHECK(access_check == access); 3631cb0ef41Sopenharmony_ci#endif 3641cb0ef41Sopenharmony_ci int offset; 3651cb0ef41Sopenharmony_ci if (overflowed) { 3661cb0ef41Sopenharmony_ci offset = (instr_at(pc) & kImm16Mask) << 16; 3671cb0ef41Sopenharmony_ci offset += SIGN_EXT_IMM16(instr_at(pc + kInstrSize) & kImm16Mask); 3681cb0ef41Sopenharmony_ci DCHECK(!is_int16(offset)); 3691cb0ef41Sopenharmony_ci } else { 3701cb0ef41Sopenharmony_ci offset = SIGN_EXT_IMM16((instr_at(pc) & kImm16Mask)); 3711cb0ef41Sopenharmony_ci } 3721cb0ef41Sopenharmony_ci return offset; 3731cb0ef41Sopenharmony_ci} 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_civoid Assembler::PatchConstantPoolAccessInstruction( 3761cb0ef41Sopenharmony_ci int pc_offset, int offset, ConstantPoolEntry::Access access, 3771cb0ef41Sopenharmony_ci ConstantPoolEntry::Type type) { 3781cb0ef41Sopenharmony_ci Address pc = reinterpret_cast<Address>(buffer_start_) + pc_offset; 3791cb0ef41Sopenharmony_ci bool overflowed = (access == ConstantPoolEntry::OVERFLOWED); 3801cb0ef41Sopenharmony_ci CHECK(overflowed != is_int16(offset)); 3811cb0ef41Sopenharmony_ci#ifdef DEBUG 3821cb0ef41Sopenharmony_ci ConstantPoolEntry::Access access_check = 3831cb0ef41Sopenharmony_ci static_cast<ConstantPoolEntry::Access>(-1); 3841cb0ef41Sopenharmony_ci DCHECK(IsConstantPoolLoadStart(pc, &access_check)); 3851cb0ef41Sopenharmony_ci DCHECK(access_check == access); 3861cb0ef41Sopenharmony_ci#endif 3871cb0ef41Sopenharmony_ci if (overflowed) { 3881cb0ef41Sopenharmony_ci int hi_word = static_cast<int>(offset >> 16); 3891cb0ef41Sopenharmony_ci int lo_word = static_cast<int>(offset & 0xffff); 3901cb0ef41Sopenharmony_ci if (lo_word & 0x8000) hi_word++; 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_ci Instr instr1 = instr_at(pc); 3931cb0ef41Sopenharmony_ci Instr instr2 = instr_at(pc + kInstrSize); 3941cb0ef41Sopenharmony_ci instr1 &= ~kImm16Mask; 3951cb0ef41Sopenharmony_ci instr1 |= (hi_word & kImm16Mask); 3961cb0ef41Sopenharmony_ci instr2 &= ~kImm16Mask; 3971cb0ef41Sopenharmony_ci instr2 |= (lo_word & kImm16Mask); 3981cb0ef41Sopenharmony_ci instr_at_put(pc, instr1); 3991cb0ef41Sopenharmony_ci instr_at_put(pc + kInstrSize, instr2); 4001cb0ef41Sopenharmony_ci } else { 4011cb0ef41Sopenharmony_ci Instr instr = instr_at(pc); 4021cb0ef41Sopenharmony_ci instr &= ~kImm16Mask; 4031cb0ef41Sopenharmony_ci instr |= (offset & kImm16Mask); 4041cb0ef41Sopenharmony_ci instr_at_put(pc, instr); 4051cb0ef41Sopenharmony_ci } 4061cb0ef41Sopenharmony_ci} 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_ciAddress Assembler::target_constant_pool_address_at( 4091cb0ef41Sopenharmony_ci Address pc, Address constant_pool, ConstantPoolEntry::Access access, 4101cb0ef41Sopenharmony_ci ConstantPoolEntry::Type type) { 4111cb0ef41Sopenharmony_ci Address addr = constant_pool; 4121cb0ef41Sopenharmony_ci DCHECK(addr); 4131cb0ef41Sopenharmony_ci addr += GetConstantPoolOffset(pc, access, type); 4141cb0ef41Sopenharmony_ci return addr; 4151cb0ef41Sopenharmony_ci} 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_ci// This sets the branch destination (which gets loaded at the call address). 4181cb0ef41Sopenharmony_ci// This is for calls and branches within generated code. The serializer 4191cb0ef41Sopenharmony_ci// has already deserialized the mov instructions etc. 4201cb0ef41Sopenharmony_ci// There is a FIXED_SEQUENCE assumption here 4211cb0ef41Sopenharmony_civoid Assembler::deserialization_set_special_target_at( 4221cb0ef41Sopenharmony_ci Address instruction_payload, Code code, Address target) { 4231cb0ef41Sopenharmony_ci set_target_address_at(instruction_payload, 4241cb0ef41Sopenharmony_ci !code.is_null() ? code.constant_pool() : kNullAddress, 4251cb0ef41Sopenharmony_ci target); 4261cb0ef41Sopenharmony_ci} 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ciint Assembler::deserialization_special_target_size( 4291cb0ef41Sopenharmony_ci Address instruction_payload) { 4301cb0ef41Sopenharmony_ci return kSpecialTargetSize; 4311cb0ef41Sopenharmony_ci} 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_civoid Assembler::deserialization_set_target_internal_reference_at( 4341cb0ef41Sopenharmony_ci Address pc, Address target, RelocInfo::Mode mode) { 4351cb0ef41Sopenharmony_ci if (RelocInfo::IsInternalReferenceEncoded(mode)) { 4361cb0ef41Sopenharmony_ci set_target_address_at(pc, kNullAddress, target, SKIP_ICACHE_FLUSH); 4371cb0ef41Sopenharmony_ci } else { 4381cb0ef41Sopenharmony_ci Memory<Address>(pc) = target; 4391cb0ef41Sopenharmony_ci } 4401cb0ef41Sopenharmony_ci} 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_ci// This code assumes the FIXED_SEQUENCE of lis/ori 4431cb0ef41Sopenharmony_civoid Assembler::set_target_address_at(Address pc, Address constant_pool, 4441cb0ef41Sopenharmony_ci Address target, 4451cb0ef41Sopenharmony_ci ICacheFlushMode icache_flush_mode) { 4461cb0ef41Sopenharmony_ci if (FLAG_enable_embedded_constant_pool && constant_pool) { 4471cb0ef41Sopenharmony_ci ConstantPoolEntry::Access access; 4481cb0ef41Sopenharmony_ci if (IsConstantPoolLoadStart(pc, &access)) { 4491cb0ef41Sopenharmony_ci Memory<Address>(target_constant_pool_address_at( 4501cb0ef41Sopenharmony_ci pc, constant_pool, access, ConstantPoolEntry::INTPTR)) = target; 4511cb0ef41Sopenharmony_ci return; 4521cb0ef41Sopenharmony_ci } 4531cb0ef41Sopenharmony_ci } 4541cb0ef41Sopenharmony_ci 4551cb0ef41Sopenharmony_ci Instr instr1 = instr_at(pc); 4561cb0ef41Sopenharmony_ci Instr instr2 = instr_at(pc + kInstrSize); 4571cb0ef41Sopenharmony_ci // Interpret 2 instructions generated by lis/ori 4581cb0ef41Sopenharmony_ci if (IsLis(instr1) && IsOri(instr2)) { 4591cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_PPC64 4601cb0ef41Sopenharmony_ci Instr instr4 = instr_at(pc + (3 * kInstrSize)); 4611cb0ef41Sopenharmony_ci Instr instr5 = instr_at(pc + (4 * kInstrSize)); 4621cb0ef41Sopenharmony_ci // Needs to be fixed up when mov changes to handle 64-bit values. 4631cb0ef41Sopenharmony_ci uint32_t* p = reinterpret_cast<uint32_t*>(pc); 4641cb0ef41Sopenharmony_ci uintptr_t itarget = static_cast<uintptr_t>(target); 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_ci instr5 &= ~kImm16Mask; 4671cb0ef41Sopenharmony_ci instr5 |= itarget & kImm16Mask; 4681cb0ef41Sopenharmony_ci itarget = itarget >> 16; 4691cb0ef41Sopenharmony_ci 4701cb0ef41Sopenharmony_ci instr4 &= ~kImm16Mask; 4711cb0ef41Sopenharmony_ci instr4 |= itarget & kImm16Mask; 4721cb0ef41Sopenharmony_ci itarget = itarget >> 16; 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci instr2 &= ~kImm16Mask; 4751cb0ef41Sopenharmony_ci instr2 |= itarget & kImm16Mask; 4761cb0ef41Sopenharmony_ci itarget = itarget >> 16; 4771cb0ef41Sopenharmony_ci 4781cb0ef41Sopenharmony_ci instr1 &= ~kImm16Mask; 4791cb0ef41Sopenharmony_ci instr1 |= itarget & kImm16Mask; 4801cb0ef41Sopenharmony_ci itarget = itarget >> 16; 4811cb0ef41Sopenharmony_ci 4821cb0ef41Sopenharmony_ci *p = instr1; 4831cb0ef41Sopenharmony_ci *(p + 1) = instr2; 4841cb0ef41Sopenharmony_ci *(p + 3) = instr4; 4851cb0ef41Sopenharmony_ci *(p + 4) = instr5; 4861cb0ef41Sopenharmony_ci if (icache_flush_mode != SKIP_ICACHE_FLUSH) { 4871cb0ef41Sopenharmony_ci FlushInstructionCache(p, 5 * kInstrSize); 4881cb0ef41Sopenharmony_ci } 4891cb0ef41Sopenharmony_ci#else 4901cb0ef41Sopenharmony_ci uint32_t* p = reinterpret_cast<uint32_t*>(pc); 4911cb0ef41Sopenharmony_ci uint32_t itarget = static_cast<uint32_t>(target); 4921cb0ef41Sopenharmony_ci int lo_word = itarget & kImm16Mask; 4931cb0ef41Sopenharmony_ci int hi_word = itarget >> 16; 4941cb0ef41Sopenharmony_ci instr1 &= ~kImm16Mask; 4951cb0ef41Sopenharmony_ci instr1 |= hi_word; 4961cb0ef41Sopenharmony_ci instr2 &= ~kImm16Mask; 4971cb0ef41Sopenharmony_ci instr2 |= lo_word; 4981cb0ef41Sopenharmony_ci 4991cb0ef41Sopenharmony_ci *p = instr1; 5001cb0ef41Sopenharmony_ci *(p + 1) = instr2; 5011cb0ef41Sopenharmony_ci if (icache_flush_mode != SKIP_ICACHE_FLUSH) { 5021cb0ef41Sopenharmony_ci FlushInstructionCache(p, 2 * kInstrSize); 5031cb0ef41Sopenharmony_ci } 5041cb0ef41Sopenharmony_ci#endif 5051cb0ef41Sopenharmony_ci return; 5061cb0ef41Sopenharmony_ci } 5071cb0ef41Sopenharmony_ci UNREACHABLE(); 5081cb0ef41Sopenharmony_ci} 5091cb0ef41Sopenharmony_ci} // namespace internal 5101cb0ef41Sopenharmony_ci} // namespace v8 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_ci#endif // V8_CODEGEN_PPC_ASSEMBLER_PPC_INL_H_ 513