37 #ifndef V8_MIPS_ASSEMBLER_MIPS_INL_H_ 38 #define V8_MIPS_ASSEMBLER_MIPS_INL_H_ 40 #include "src/mips/assembler-mips.h" 42 #include "src/assembler.h" 43 #include "src/debug/debug.h" 44 #include "src/objects-inl.h" 49 bool CpuFeatures::SupportsOptimizer() {
return IsSupported(FPU); }
51 bool CpuFeatures::SupportsWasmSimd128() {
return IsSupported(MIPS_SIMD); }
56 bool Operand::is_reg()
const {
57 return rm_.is_valid();
60 int32_t Operand::immediate()
const {
62 DCHECK(!IsHeapObjectRequest());
63 return value_.immediate;
69 void RelocInfo::apply(intptr_t delta) {
70 if (IsInternalReference(rmode_) || IsInternalReferenceEncoded(rmode_)) {
72 Assembler::RelocateInternalReference(rmode_, pc_, delta);
73 }
else if (IsRelativeCodeTarget(rmode_)) {
74 Assembler::RelocateRelativeReference(rmode_, pc_, delta);
79 Address RelocInfo::target_address() {
80 DCHECK(IsCodeTargetMode(rmode_) || IsRuntimeEntry(rmode_) ||
82 return Assembler::target_address_at(pc_, constant_pool_);
85 Address RelocInfo::target_address_address() {
86 DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
87 IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
88 IsOffHeapTarget(rmode_));
103 if (IsMipsArchVariant(kMips32r6)) {
107 return pc_ + (Assembler::kInstructionsFor32BitConstant - 1) * kInstrSize;
109 return pc_ + Assembler::kInstructionsFor32BitConstant * kInstrSize;
113 Address RelocInfo::constant_pool_entry_address() {
118 int RelocInfo::target_address_size() {
119 return Assembler::kSpecialTargetSize;
122 Address Assembler::target_address_from_return_address(Address pc) {
123 return pc - kCallTargetAddressOffset;
126 void Assembler::deserialization_set_special_target_at(
127 Address instruction_payload, Code code, Address target) {
128 if (IsMipsArchVariant(kMips32r6)) {
130 set_target_address_at(
131 instruction_payload - (kInstructionsFor32BitConstant - 1) * kInstrSize,
132 code ? code->constant_pool() : kNullAddress, target);
134 set_target_address_at(
135 instruction_payload - kInstructionsFor32BitConstant * kInstrSize,
136 code ? code->constant_pool() : kNullAddress, target);
140 int Assembler::deserialization_special_target_size(
141 Address instruction_payload) {
142 return kSpecialTargetSize;
145 void Assembler::set_target_internal_reference_encoded_at(Address pc,
147 Instr instr1 = Assembler::instr_at(pc + 0 * kInstrSize);
148 Instr instr2 = Assembler::instr_at(pc + 1 * kInstrSize);
149 DCHECK(Assembler::IsLui(instr1));
150 DCHECK(Assembler::IsOri(instr2) || Assembler::IsJicOrJialc(instr2));
151 instr1 &= ~kImm16Mask;
152 instr2 &= ~kImm16Mask;
153 int32_t imm =
static_cast<int32_t
>(target);
154 DCHECK_EQ(imm & 3, 0);
155 if (Assembler::IsJicOrJialc(instr2)) {
157 uint32_t lui_offset_u, jic_offset_u;
158 Assembler::UnpackTargetAddressUnsigned(imm, lui_offset_u, jic_offset_u);
160 Assembler::instr_at_put(pc + 0 * kInstrSize, instr1 | lui_offset_u);
161 Assembler::instr_at_put(pc + 1 * kInstrSize, instr2 | jic_offset_u);
164 PatchLuiOriImmediate(pc, imm, instr1, 0 * kInstrSize, instr2,
172 void Assembler::deserialization_set_target_internal_reference_at(
173 Address pc, Address target, RelocInfo::Mode mode) {
174 if (RelocInfo::IsInternalReferenceEncoded(mode)) {
175 DCHECK(IsLui(instr_at(pc)));
176 set_target_internal_reference_encoded_at(pc, target);
178 DCHECK(RelocInfo::IsInternalReference(mode));
179 Memory<Address>(pc) = target;
183 HeapObject* RelocInfo::target_object() {
184 DCHECK(IsCodeTarget(rmode_) || IsEmbeddedObject(rmode_));
185 return HeapObject::cast(reinterpret_cast<Object*>(
186 Assembler::target_address_at(pc_, constant_pool_)));
189 Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
190 if (IsCodeTarget(rmode_) || IsEmbeddedObject(rmode_)) {
191 return Handle<HeapObject>(
reinterpret_cast<Address*
>(
192 Assembler::target_address_at(pc_, constant_pool_)));
194 DCHECK(IsRelativeCodeTarget(rmode_));
195 return origin->relative_code_target_object_handle_at(pc_);
198 void RelocInfo::set_target_object(Heap* heap, HeapObject* target,
199 WriteBarrierMode write_barrier_mode,
200 ICacheFlushMode icache_flush_mode) {
201 DCHECK(IsCodeTarget(rmode_) || IsEmbeddedObject(rmode_));
202 Assembler::set_target_address_at(pc_, constant_pool_,
203 reinterpret_cast<Address>(target),
205 if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() !=
nullptr) {
206 WriteBarrierForCode(host(),
this, target);
211 Address RelocInfo::target_external_reference() {
212 DCHECK(IsExternalReference(rmode_));
213 return Assembler::target_address_at(pc_, constant_pool_);
216 void RelocInfo::set_target_external_reference(
217 Address target, ICacheFlushMode icache_flush_mode) {
218 DCHECK(IsExternalReference(rmode_));
219 Assembler::set_target_address_at(pc_, constant_pool_, target,
223 Address RelocInfo::target_internal_reference() {
224 if (IsInternalReference(rmode_)) {
225 return Memory<Address>(pc_);
229 DCHECK(IsInternalReferenceEncoded(rmode_));
230 Instr instr1 = Assembler::instr_at(pc_ + 0 * kInstrSize);
231 Instr instr2 = Assembler::instr_at(pc_ + 1 * kInstrSize);
232 DCHECK(Assembler::IsLui(instr1));
233 DCHECK(Assembler::IsOri(instr2) || Assembler::IsJicOrJialc(instr2));
234 if (Assembler::IsJicOrJialc(instr2)) {
235 return static_cast<Address
>(
236 Assembler::CreateTargetAddress(instr1, instr2));
238 return static_cast<Address
>(Assembler::GetLuiOriImmediate(instr1, instr2));
243 Address RelocInfo::target_internal_reference_address() {
244 DCHECK(IsInternalReference(rmode_) || IsInternalReferenceEncoded(rmode_));
248 Address RelocInfo::target_runtime_entry(Assembler* origin) {
249 DCHECK(IsRuntimeEntry(rmode_));
250 return target_address();
253 void RelocInfo::set_target_runtime_entry(Address target,
254 WriteBarrierMode write_barrier_mode,
255 ICacheFlushMode icache_flush_mode) {
256 DCHECK(IsRuntimeEntry(rmode_));
257 if (target_address() != target)
258 set_target_address(target, write_barrier_mode, icache_flush_mode);
261 Address RelocInfo::target_off_heap_target() {
262 DCHECK(IsOffHeapTarget(rmode_));
263 return Assembler::target_address_at(pc_, constant_pool_);
266 void RelocInfo::WipeOut() {
267 DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
268 IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
269 IsInternalReference(rmode_) || IsInternalReferenceEncoded(rmode_) ||
270 IsOffHeapTarget(rmode_));
271 if (IsInternalReference(rmode_)) {
272 Memory<Address>(pc_) = kNullAddress;
273 }
else if (IsInternalReferenceEncoded(rmode_)) {
274 Assembler::set_target_internal_reference_encoded_at(pc_, kNullAddress);
276 Assembler::set_target_address_at(pc_, constant_pool_, kNullAddress);
280 Handle<Code> Assembler::relative_code_target_object_handle_at(
282 Instr instr1 = instr_at(pc);
283 Instr instr2 = instr_at(pc + kInstrSize);
284 DCHECK(IsLui(instr1));
285 DCHECK(IsOri(instr2) || IsNal(instr2));
286 DCHECK(IsNal(instr2) || IsNal(instr_at(pc - kInstrSize)));
288 instr2 = instr_at(pc + 2 * kInstrSize);
291 int code_target_index = GetLuiOriImmediate(instr1, instr2);
292 return GetCodeTarget(code_target_index);
295 template <
typename ObjectVisitor>
296 void RelocInfo::Visit(ObjectVisitor* visitor) {
298 if (IsEmbeddedObject(mode)) {
299 visitor->VisitEmbeddedPointer(host(),
this);
300 }
else if (IsCodeTargetMode(mode)) {
301 visitor->VisitCodeTarget(host(),
this);
302 }
else if (IsExternalReference(mode)) {
303 visitor->VisitExternalReference(host(),
this);
304 }
else if (IsInternalReference(mode) || IsInternalReferenceEncoded(mode)) {
305 visitor->VisitInternalReference(host(),
this);
306 }
else if (IsRuntimeEntry(mode)) {
307 visitor->VisitRuntimeEntry(host(),
this);
308 }
else if (IsOffHeapTarget(mode)) {
309 visitor->VisitOffHeapTarget(host(),
this);
317 void Assembler::CheckBuffer() {
318 if (buffer_space() <= kGap) {
324 void Assembler::CheckForEmitInForbiddenSlot() {
325 if (!is_buffer_growth_blocked()) {
328 if (IsPrevInstrCompactBranch()) {
330 Instr nop = SPECIAL | SLL;
331 *
reinterpret_cast<Instr*
>(pc_) = nop;
334 ClearCompactBranchState();
339 void Assembler::EmitHelper(Instr x, CompactBranchType is_compact_branch) {
340 if (IsPrevInstrCompactBranch()) {
341 if (Instruction::IsForbiddenAfterBranchInstr(x)) {
343 Instr nop = SPECIAL | SLL;
344 *
reinterpret_cast<Instr*
>(pc_) = nop;
347 ClearCompactBranchState();
349 *
reinterpret_cast<Instr*
>(pc_) = x;
351 if (is_compact_branch == CompactBranchType::COMPACT_BRANCH) {
352 EmittedCompactBranchInstruction();
354 CheckTrampolinePoolQuick();
358 inline void Assembler::EmitHelper(uint8_t x);
360 template <
typename T>
361 void Assembler::EmitHelper(T x) {
362 *
reinterpret_cast<T*
>(pc_) = x;
364 CheckTrampolinePoolQuick();
368 void Assembler::EmitHelper(uint8_t x) {
369 *
reinterpret_cast<uint8_t*
>(pc_) = x;
371 if (reinterpret_cast<intptr_t>(pc_) % kInstrSize == 0) {
372 CheckTrampolinePoolQuick();
376 void Assembler::emit(Instr x, CompactBranchType is_compact_branch) {
377 if (!is_buffer_growth_blocked()) {
380 EmitHelper(x, is_compact_branch);
383 EnsureSpace::EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
388 #endif // V8_MIPS_ASSEMBLER_MIPS_INL_H_