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 are 61cb0ef41Sopenharmony_ci// 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 distribution. 141cb0ef41Sopenharmony_ci// 151cb0ef41Sopenharmony_ci// - Neither the name of Sun Microsystems or the names of contributors may 161cb0ef41Sopenharmony_ci// be used to endorse or promote products derived from this software without 171cb0ef41Sopenharmony_ci// specific prior written permission. 181cb0ef41Sopenharmony_ci// 191cb0ef41Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 201cb0ef41Sopenharmony_ci// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 211cb0ef41Sopenharmony_ci// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 221cb0ef41Sopenharmony_ci// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 231cb0ef41Sopenharmony_ci// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 241cb0ef41Sopenharmony_ci// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 251cb0ef41Sopenharmony_ci// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 261cb0ef41Sopenharmony_ci// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 271cb0ef41Sopenharmony_ci// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 281cb0ef41Sopenharmony_ci// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 291cb0ef41Sopenharmony_ci// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci// The original source code covered by the above license above has been 321cb0ef41Sopenharmony_ci// modified significantly by Google Inc. 331cb0ef41Sopenharmony_ci// Copyright 2012 the V8 project authors. All rights reserved. 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci#include "src/codegen/mips64/assembler-mips64.h" 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_MIPS64 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci#include "src/base/cpu.h" 401cb0ef41Sopenharmony_ci#include "src/codegen/machine-type.h" 411cb0ef41Sopenharmony_ci#include "src/codegen/mips64/assembler-mips64-inl.h" 421cb0ef41Sopenharmony_ci#include "src/codegen/safepoint-table.h" 431cb0ef41Sopenharmony_ci#include "src/codegen/string-constants.h" 441cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimizer.h" 451cb0ef41Sopenharmony_ci#include "src/objects/heap-number-inl.h" 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_cinamespace v8 { 481cb0ef41Sopenharmony_cinamespace internal { 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci// Get the CPU features enabled by the build. For cross compilation the 511cb0ef41Sopenharmony_ci// preprocessor symbols CAN_USE_FPU_INSTRUCTIONS 521cb0ef41Sopenharmony_ci// can be defined to enable FPU instructions when building the 531cb0ef41Sopenharmony_ci// snapshot. 541cb0ef41Sopenharmony_cistatic unsigned CpuFeaturesImpliedByCompiler() { 551cb0ef41Sopenharmony_ci unsigned answer = 0; 561cb0ef41Sopenharmony_ci#ifdef CAN_USE_FPU_INSTRUCTIONS 571cb0ef41Sopenharmony_ci answer |= 1u << FPU; 581cb0ef41Sopenharmony_ci#endif // def CAN_USE_FPU_INSTRUCTIONS 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci // If the compiler is allowed to use FPU then we can use FPU too in our code 611cb0ef41Sopenharmony_ci // generation even when generating snapshots. This won't work for cross 621cb0ef41Sopenharmony_ci // compilation. 631cb0ef41Sopenharmony_ci#if defined(__mips__) && defined(__mips_hard_float) && __mips_hard_float != 0 641cb0ef41Sopenharmony_ci answer |= 1u << FPU; 651cb0ef41Sopenharmony_ci#endif 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci return answer; 681cb0ef41Sopenharmony_ci} 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_cibool CpuFeatures::SupportsWasmSimd128() { return IsSupported(MIPS_SIMD); } 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_civoid CpuFeatures::ProbeImpl(bool cross_compile) { 731cb0ef41Sopenharmony_ci supported_ |= CpuFeaturesImpliedByCompiler(); 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci // Only use statically determined features for cross compile (snapshot). 761cb0ef41Sopenharmony_ci if (cross_compile) return; 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci // If the compiler is allowed to use fpu then we can use fpu too in our 791cb0ef41Sopenharmony_ci // code generation. 801cb0ef41Sopenharmony_ci#ifndef __mips__ 811cb0ef41Sopenharmony_ci // For the simulator build, use FPU. 821cb0ef41Sopenharmony_ci supported_ |= 1u << FPU; 831cb0ef41Sopenharmony_ci#if defined(_MIPS_ARCH_MIPS64R6) && defined(_MIPS_MSA) 841cb0ef41Sopenharmony_ci supported_ |= 1u << MIPS_SIMD; 851cb0ef41Sopenharmony_ci#endif 861cb0ef41Sopenharmony_ci#else 871cb0ef41Sopenharmony_ci // Probe for additional features at runtime. 881cb0ef41Sopenharmony_ci base::CPU cpu; 891cb0ef41Sopenharmony_ci if (cpu.has_fpu()) supported_ |= 1u << FPU; 901cb0ef41Sopenharmony_ci#if defined(_MIPS_MSA) 911cb0ef41Sopenharmony_ci supported_ |= 1u << MIPS_SIMD; 921cb0ef41Sopenharmony_ci#else 931cb0ef41Sopenharmony_ci if (cpu.has_msa()) supported_ |= 1u << MIPS_SIMD; 941cb0ef41Sopenharmony_ci#endif 951cb0ef41Sopenharmony_ci#endif 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci // Set a static value on whether Simd is supported. 981cb0ef41Sopenharmony_ci // This variable is only used for certain archs to query SupportWasmSimd128() 991cb0ef41Sopenharmony_ci // at runtime in builtins using an extern ref. Other callers should use 1001cb0ef41Sopenharmony_ci // CpuFeatures::SupportWasmSimd128(). 1011cb0ef41Sopenharmony_ci CpuFeatures::supports_wasm_simd_128_ = CpuFeatures::SupportsWasmSimd128(); 1021cb0ef41Sopenharmony_ci} 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_civoid CpuFeatures::PrintTarget() {} 1051cb0ef41Sopenharmony_civoid CpuFeatures::PrintFeatures() {} 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ciint ToNumber(Register reg) { 1081cb0ef41Sopenharmony_ci DCHECK(reg.is_valid()); 1091cb0ef41Sopenharmony_ci const int kNumbers[] = { 1101cb0ef41Sopenharmony_ci 0, // zero_reg 1111cb0ef41Sopenharmony_ci 1, // at 1121cb0ef41Sopenharmony_ci 2, // v0 1131cb0ef41Sopenharmony_ci 3, // v1 1141cb0ef41Sopenharmony_ci 4, // a0 1151cb0ef41Sopenharmony_ci 5, // a1 1161cb0ef41Sopenharmony_ci 6, // a2 1171cb0ef41Sopenharmony_ci 7, // a3 1181cb0ef41Sopenharmony_ci 8, // a4 1191cb0ef41Sopenharmony_ci 9, // a5 1201cb0ef41Sopenharmony_ci 10, // a6 1211cb0ef41Sopenharmony_ci 11, // a7 1221cb0ef41Sopenharmony_ci 12, // t0 1231cb0ef41Sopenharmony_ci 13, // t1 1241cb0ef41Sopenharmony_ci 14, // t2 1251cb0ef41Sopenharmony_ci 15, // t3 1261cb0ef41Sopenharmony_ci 16, // s0 1271cb0ef41Sopenharmony_ci 17, // s1 1281cb0ef41Sopenharmony_ci 18, // s2 1291cb0ef41Sopenharmony_ci 19, // s3 1301cb0ef41Sopenharmony_ci 20, // s4 1311cb0ef41Sopenharmony_ci 21, // s5 1321cb0ef41Sopenharmony_ci 22, // s6 1331cb0ef41Sopenharmony_ci 23, // s7 1341cb0ef41Sopenharmony_ci 24, // t8 1351cb0ef41Sopenharmony_ci 25, // t9 1361cb0ef41Sopenharmony_ci 26, // k0 1371cb0ef41Sopenharmony_ci 27, // k1 1381cb0ef41Sopenharmony_ci 28, // gp 1391cb0ef41Sopenharmony_ci 29, // sp 1401cb0ef41Sopenharmony_ci 30, // fp 1411cb0ef41Sopenharmony_ci 31, // ra 1421cb0ef41Sopenharmony_ci }; 1431cb0ef41Sopenharmony_ci return kNumbers[reg.code()]; 1441cb0ef41Sopenharmony_ci} 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ciRegister ToRegister(int num) { 1471cb0ef41Sopenharmony_ci DCHECK(num >= 0 && num < kNumRegisters); 1481cb0ef41Sopenharmony_ci const Register kRegisters[] = { 1491cb0ef41Sopenharmony_ci zero_reg, at, v0, v1, a0, a1, a2, a3, a4, a5, a6, a7, t0, t1, t2, t3, 1501cb0ef41Sopenharmony_ci s0, s1, s2, s3, s4, s5, s6, s7, t8, t9, k0, k1, gp, sp, fp, ra}; 1511cb0ef41Sopenharmony_ci return kRegisters[num]; 1521cb0ef41Sopenharmony_ci} 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci// ----------------------------------------------------------------------------- 1551cb0ef41Sopenharmony_ci// Implementation of RelocInfo. 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ciconst int RelocInfo::kApplyMask = 1581cb0ef41Sopenharmony_ci RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | 1591cb0ef41Sopenharmony_ci RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED); 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_cibool RelocInfo::IsCodedSpecially() { 1621cb0ef41Sopenharmony_ci // The deserializer needs to know whether a pointer is specially coded. Being 1631cb0ef41Sopenharmony_ci // specially coded on MIPS means that it is a lui/ori instruction, and that is 1641cb0ef41Sopenharmony_ci // always the case inside code objects. 1651cb0ef41Sopenharmony_ci return true; 1661cb0ef41Sopenharmony_ci} 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_cibool RelocInfo::IsInConstantPool() { return false; } 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ciuint32_t RelocInfo::wasm_call_tag() const { 1711cb0ef41Sopenharmony_ci DCHECK(rmode_ == WASM_CALL || rmode_ == WASM_STUB_CALL); 1721cb0ef41Sopenharmony_ci return static_cast<uint32_t>( 1731cb0ef41Sopenharmony_ci Assembler::target_address_at(pc_, constant_pool_)); 1741cb0ef41Sopenharmony_ci} 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci// ----------------------------------------------------------------------------- 1771cb0ef41Sopenharmony_ci// Implementation of Operand and MemOperand. 1781cb0ef41Sopenharmony_ci// See assembler-mips-inl.h for inlined constructors. 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ciOperand::Operand(Handle<HeapObject> handle) 1811cb0ef41Sopenharmony_ci : rm_(no_reg), rmode_(RelocInfo::FULL_EMBEDDED_OBJECT) { 1821cb0ef41Sopenharmony_ci value_.immediate = static_cast<intptr_t>(handle.address()); 1831cb0ef41Sopenharmony_ci} 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ciOperand Operand::EmbeddedNumber(double value) { 1861cb0ef41Sopenharmony_ci int32_t smi; 1871cb0ef41Sopenharmony_ci if (DoubleToSmiInteger(value, &smi)) return Operand(Smi::FromInt(smi)); 1881cb0ef41Sopenharmony_ci Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT); 1891cb0ef41Sopenharmony_ci result.is_heap_object_request_ = true; 1901cb0ef41Sopenharmony_ci result.value_.heap_object_request = HeapObjectRequest(value); 1911cb0ef41Sopenharmony_ci return result; 1921cb0ef41Sopenharmony_ci} 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ciOperand Operand::EmbeddedStringConstant(const StringConstantBase* str) { 1951cb0ef41Sopenharmony_ci Operand result(0, RelocInfo::FULL_EMBEDDED_OBJECT); 1961cb0ef41Sopenharmony_ci result.is_heap_object_request_ = true; 1971cb0ef41Sopenharmony_ci result.value_.heap_object_request = HeapObjectRequest(str); 1981cb0ef41Sopenharmony_ci return result; 1991cb0ef41Sopenharmony_ci} 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ciMemOperand::MemOperand(Register rm, int32_t offset) : Operand(rm) { 2021cb0ef41Sopenharmony_ci offset_ = offset; 2031cb0ef41Sopenharmony_ci} 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ciMemOperand::MemOperand(Register rm, int32_t unit, int32_t multiplier, 2061cb0ef41Sopenharmony_ci OffsetAddend offset_addend) 2071cb0ef41Sopenharmony_ci : Operand(rm) { 2081cb0ef41Sopenharmony_ci offset_ = unit * multiplier + offset_addend; 2091cb0ef41Sopenharmony_ci} 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_civoid Assembler::AllocateAndInstallRequestedHeapObjects(Isolate* isolate) { 2121cb0ef41Sopenharmony_ci DCHECK_IMPLIES(isolate == nullptr, heap_object_requests_.empty()); 2131cb0ef41Sopenharmony_ci for (auto& request : heap_object_requests_) { 2141cb0ef41Sopenharmony_ci Handle<HeapObject> object; 2151cb0ef41Sopenharmony_ci switch (request.kind()) { 2161cb0ef41Sopenharmony_ci case HeapObjectRequest::kHeapNumber: 2171cb0ef41Sopenharmony_ci object = isolate->factory()->NewHeapNumber<AllocationType::kOld>( 2181cb0ef41Sopenharmony_ci request.heap_number()); 2191cb0ef41Sopenharmony_ci break; 2201cb0ef41Sopenharmony_ci case HeapObjectRequest::kStringConstant: 2211cb0ef41Sopenharmony_ci const StringConstantBase* str = request.string(); 2221cb0ef41Sopenharmony_ci CHECK_NOT_NULL(str); 2231cb0ef41Sopenharmony_ci object = str->AllocateStringConstant(isolate); 2241cb0ef41Sopenharmony_ci break; 2251cb0ef41Sopenharmony_ci } 2261cb0ef41Sopenharmony_ci Address pc = reinterpret_cast<Address>(buffer_start_) + request.offset(); 2271cb0ef41Sopenharmony_ci set_target_value_at(pc, reinterpret_cast<uint64_t>(object.location())); 2281cb0ef41Sopenharmony_ci } 2291cb0ef41Sopenharmony_ci} 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci// ----------------------------------------------------------------------------- 2321cb0ef41Sopenharmony_ci// Specific instructions, constants, and masks. 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci// daddiu(sp, sp, 8) aka Pop() operation or part of Pop(r) 2351cb0ef41Sopenharmony_ci// operations as post-increment of sp. 2361cb0ef41Sopenharmony_ciconst Instr kPopInstruction = DADDIU | (sp.code() << kRsShift) | 2371cb0ef41Sopenharmony_ci (sp.code() << kRtShift) | 2381cb0ef41Sopenharmony_ci (kPointerSize & kImm16Mask); 2391cb0ef41Sopenharmony_ci// daddiu(sp, sp, -8) part of Push(r) operation as pre-decrement of sp. 2401cb0ef41Sopenharmony_ciconst Instr kPushInstruction = DADDIU | (sp.code() << kRsShift) | 2411cb0ef41Sopenharmony_ci (sp.code() << kRtShift) | 2421cb0ef41Sopenharmony_ci (-kPointerSize & kImm16Mask); 2431cb0ef41Sopenharmony_ci// Sd(r, MemOperand(sp, 0)) 2441cb0ef41Sopenharmony_ciconst Instr kPushRegPattern = SD | (sp.code() << kRsShift) | (0 & kImm16Mask); 2451cb0ef41Sopenharmony_ci// Ld(r, MemOperand(sp, 0)) 2461cb0ef41Sopenharmony_ciconst Instr kPopRegPattern = LD | (sp.code() << kRsShift) | (0 & kImm16Mask); 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ciconst Instr kLwRegFpOffsetPattern = 2491cb0ef41Sopenharmony_ci LW | (fp.code() << kRsShift) | (0 & kImm16Mask); 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ciconst Instr kSwRegFpOffsetPattern = 2521cb0ef41Sopenharmony_ci SW | (fp.code() << kRsShift) | (0 & kImm16Mask); 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ciconst Instr kLwRegFpNegOffsetPattern = 2551cb0ef41Sopenharmony_ci LW | (fp.code() << kRsShift) | (kNegOffset & kImm16Mask); 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_ciconst Instr kSwRegFpNegOffsetPattern = 2581cb0ef41Sopenharmony_ci SW | (fp.code() << kRsShift) | (kNegOffset & kImm16Mask); 2591cb0ef41Sopenharmony_ci// A mask for the Rt register for push, pop, lw, sw instructions. 2601cb0ef41Sopenharmony_ciconst Instr kRtMask = kRtFieldMask; 2611cb0ef41Sopenharmony_ciconst Instr kLwSwInstrTypeMask = 0xFFE00000; 2621cb0ef41Sopenharmony_ciconst Instr kLwSwInstrArgumentMask = ~kLwSwInstrTypeMask; 2631cb0ef41Sopenharmony_ciconst Instr kLwSwOffsetMask = kImm16Mask; 2641cb0ef41Sopenharmony_ci 2651cb0ef41Sopenharmony_ciAssembler::Assembler(const AssemblerOptions& options, 2661cb0ef41Sopenharmony_ci std::unique_ptr<AssemblerBuffer> buffer) 2671cb0ef41Sopenharmony_ci : AssemblerBase(options, std::move(buffer)), 2681cb0ef41Sopenharmony_ci scratch_register_list_({at, s0}) { 2691cb0ef41Sopenharmony_ci if (CpuFeatures::IsSupported(MIPS_SIMD)) { 2701cb0ef41Sopenharmony_ci EnableCpuFeature(MIPS_SIMD); 2711cb0ef41Sopenharmony_ci } 2721cb0ef41Sopenharmony_ci reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_); 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci last_trampoline_pool_end_ = 0; 2751cb0ef41Sopenharmony_ci no_trampoline_pool_before_ = 0; 2761cb0ef41Sopenharmony_ci trampoline_pool_blocked_nesting_ = 0; 2771cb0ef41Sopenharmony_ci // We leave space (16 * kTrampolineSlotsSize) 2781cb0ef41Sopenharmony_ci // for BlockTrampolinePoolScope buffer. 2791cb0ef41Sopenharmony_ci next_buffer_check_ = FLAG_force_long_branches 2801cb0ef41Sopenharmony_ci ? kMaxInt 2811cb0ef41Sopenharmony_ci : kMaxBranchOffset - kTrampolineSlotsSize * 16; 2821cb0ef41Sopenharmony_ci internal_trampoline_exception_ = false; 2831cb0ef41Sopenharmony_ci last_bound_pos_ = 0; 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci trampoline_emitted_ = FLAG_force_long_branches; 2861cb0ef41Sopenharmony_ci unbound_labels_count_ = 0; 2871cb0ef41Sopenharmony_ci block_buffer_growth_ = false; 2881cb0ef41Sopenharmony_ci} 2891cb0ef41Sopenharmony_ci 2901cb0ef41Sopenharmony_civoid Assembler::GetCode(Isolate* isolate, CodeDesc* desc, 2911cb0ef41Sopenharmony_ci SafepointTableBuilder* safepoint_table_builder, 2921cb0ef41Sopenharmony_ci int handler_table_offset) { 2931cb0ef41Sopenharmony_ci // As a crutch to avoid having to add manual Align calls wherever we use a 2941cb0ef41Sopenharmony_ci // raw workflow to create Code objects (mostly in tests), add another Align 2951cb0ef41Sopenharmony_ci // call here. It does no harm - the end of the Code object is aligned to the 2961cb0ef41Sopenharmony_ci // (larger) kCodeAlignment anyways. 2971cb0ef41Sopenharmony_ci // TODO(jgruber): Consider moving responsibility for proper alignment to 2981cb0ef41Sopenharmony_ci // metadata table builders (safepoint, handler, constant pool, code 2991cb0ef41Sopenharmony_ci // comments). 3001cb0ef41Sopenharmony_ci DataAlign(Code::kMetadataAlignment); 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci EmitForbiddenSlotInstruction(); 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci int code_comments_size = WriteCodeComments(); 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap. 3071cb0ef41Sopenharmony_ci 3081cb0ef41Sopenharmony_ci AllocateAndInstallRequestedHeapObjects(isolate); 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci // Set up code descriptor. 3111cb0ef41Sopenharmony_ci // TODO(jgruber): Reconsider how these offsets and sizes are maintained up to 3121cb0ef41Sopenharmony_ci // this point to make CodeDesc initialization less fiddly. 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci static constexpr int kConstantPoolSize = 0; 3151cb0ef41Sopenharmony_ci const int instruction_size = pc_offset(); 3161cb0ef41Sopenharmony_ci const int code_comments_offset = instruction_size - code_comments_size; 3171cb0ef41Sopenharmony_ci const int constant_pool_offset = code_comments_offset - kConstantPoolSize; 3181cb0ef41Sopenharmony_ci const int handler_table_offset2 = (handler_table_offset == kNoHandlerTable) 3191cb0ef41Sopenharmony_ci ? constant_pool_offset 3201cb0ef41Sopenharmony_ci : handler_table_offset; 3211cb0ef41Sopenharmony_ci const int safepoint_table_offset = 3221cb0ef41Sopenharmony_ci (safepoint_table_builder == kNoSafepointTable) 3231cb0ef41Sopenharmony_ci ? handler_table_offset2 3241cb0ef41Sopenharmony_ci : safepoint_table_builder->safepoint_table_offset(); 3251cb0ef41Sopenharmony_ci const int reloc_info_offset = 3261cb0ef41Sopenharmony_ci static_cast<int>(reloc_info_writer.pos() - buffer_->start()); 3271cb0ef41Sopenharmony_ci CodeDesc::Initialize(desc, this, safepoint_table_offset, 3281cb0ef41Sopenharmony_ci handler_table_offset2, constant_pool_offset, 3291cb0ef41Sopenharmony_ci code_comments_offset, reloc_info_offset); 3301cb0ef41Sopenharmony_ci} 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_civoid Assembler::Align(int m) { 3331cb0ef41Sopenharmony_ci DCHECK(m >= 4 && base::bits::IsPowerOfTwo(m)); 3341cb0ef41Sopenharmony_ci EmitForbiddenSlotInstruction(); 3351cb0ef41Sopenharmony_ci while ((pc_offset() & (m - 1)) != 0) { 3361cb0ef41Sopenharmony_ci nop(); 3371cb0ef41Sopenharmony_ci } 3381cb0ef41Sopenharmony_ci} 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_civoid Assembler::CodeTargetAlign() { 3411cb0ef41Sopenharmony_ci // No advantage to aligning branch/call targets to more than 3421cb0ef41Sopenharmony_ci // single instruction, that I am aware of. 3431cb0ef41Sopenharmony_ci Align(4); 3441cb0ef41Sopenharmony_ci} 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_ciRegister Assembler::GetRtReg(Instr instr) { 3471cb0ef41Sopenharmony_ci return Register::from_code((instr & kRtFieldMask) >> kRtShift); 3481cb0ef41Sopenharmony_ci} 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ciRegister Assembler::GetRsReg(Instr instr) { 3511cb0ef41Sopenharmony_ci return Register::from_code((instr & kRsFieldMask) >> kRsShift); 3521cb0ef41Sopenharmony_ci} 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ciRegister Assembler::GetRdReg(Instr instr) { 3551cb0ef41Sopenharmony_ci return Register::from_code((instr & kRdFieldMask) >> kRdShift); 3561cb0ef41Sopenharmony_ci} 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ciuint32_t Assembler::GetRt(Instr instr) { 3591cb0ef41Sopenharmony_ci return (instr & kRtFieldMask) >> kRtShift; 3601cb0ef41Sopenharmony_ci} 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ciuint32_t Assembler::GetRtField(Instr instr) { return instr & kRtFieldMask; } 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ciuint32_t Assembler::GetRs(Instr instr) { 3651cb0ef41Sopenharmony_ci return (instr & kRsFieldMask) >> kRsShift; 3661cb0ef41Sopenharmony_ci} 3671cb0ef41Sopenharmony_ci 3681cb0ef41Sopenharmony_ciuint32_t Assembler::GetRsField(Instr instr) { return instr & kRsFieldMask; } 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_ciuint32_t Assembler::GetRd(Instr instr) { 3711cb0ef41Sopenharmony_ci return (instr & kRdFieldMask) >> kRdShift; 3721cb0ef41Sopenharmony_ci} 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ciuint32_t Assembler::GetRdField(Instr instr) { return instr & kRdFieldMask; } 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ciuint32_t Assembler::GetSa(Instr instr) { 3771cb0ef41Sopenharmony_ci return (instr & kSaFieldMask) >> kSaShift; 3781cb0ef41Sopenharmony_ci} 3791cb0ef41Sopenharmony_ci 3801cb0ef41Sopenharmony_ciuint32_t Assembler::GetSaField(Instr instr) { return instr & kSaFieldMask; } 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ciuint32_t Assembler::GetOpcodeField(Instr instr) { return instr & kOpcodeMask; } 3831cb0ef41Sopenharmony_ci 3841cb0ef41Sopenharmony_ciuint32_t Assembler::GetFunction(Instr instr) { 3851cb0ef41Sopenharmony_ci return (instr & kFunctionFieldMask) >> kFunctionShift; 3861cb0ef41Sopenharmony_ci} 3871cb0ef41Sopenharmony_ci 3881cb0ef41Sopenharmony_ciuint32_t Assembler::GetFunctionField(Instr instr) { 3891cb0ef41Sopenharmony_ci return instr & kFunctionFieldMask; 3901cb0ef41Sopenharmony_ci} 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_ciuint32_t Assembler::GetImmediate16(Instr instr) { return instr & kImm16Mask; } 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_ciuint32_t Assembler::GetLabelConst(Instr instr) { return instr & ~kImm16Mask; } 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_cibool Assembler::IsPop(Instr instr) { 3971cb0ef41Sopenharmony_ci return (instr & ~kRtMask) == kPopRegPattern; 3981cb0ef41Sopenharmony_ci} 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_cibool Assembler::IsPush(Instr instr) { 4011cb0ef41Sopenharmony_ci return (instr & ~kRtMask) == kPushRegPattern; 4021cb0ef41Sopenharmony_ci} 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_cibool Assembler::IsSwRegFpOffset(Instr instr) { 4051cb0ef41Sopenharmony_ci return ((instr & kLwSwInstrTypeMask) == kSwRegFpOffsetPattern); 4061cb0ef41Sopenharmony_ci} 4071cb0ef41Sopenharmony_ci 4081cb0ef41Sopenharmony_cibool Assembler::IsLwRegFpOffset(Instr instr) { 4091cb0ef41Sopenharmony_ci return ((instr & kLwSwInstrTypeMask) == kLwRegFpOffsetPattern); 4101cb0ef41Sopenharmony_ci} 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_cibool Assembler::IsSwRegFpNegOffset(Instr instr) { 4131cb0ef41Sopenharmony_ci return ((instr & (kLwSwInstrTypeMask | kNegOffset)) == 4141cb0ef41Sopenharmony_ci kSwRegFpNegOffsetPattern); 4151cb0ef41Sopenharmony_ci} 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_cibool Assembler::IsLwRegFpNegOffset(Instr instr) { 4181cb0ef41Sopenharmony_ci return ((instr & (kLwSwInstrTypeMask | kNegOffset)) == 4191cb0ef41Sopenharmony_ci kLwRegFpNegOffsetPattern); 4201cb0ef41Sopenharmony_ci} 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci// Labels refer to positions in the (to be) generated code. 4231cb0ef41Sopenharmony_ci// There are bound, linked, and unused labels. 4241cb0ef41Sopenharmony_ci// 4251cb0ef41Sopenharmony_ci// Bound labels refer to known positions in the already 4261cb0ef41Sopenharmony_ci// generated code. pos() is the position the label refers to. 4271cb0ef41Sopenharmony_ci// 4281cb0ef41Sopenharmony_ci// Linked labels refer to unknown positions in the code 4291cb0ef41Sopenharmony_ci// to be generated; pos() is the position of the last 4301cb0ef41Sopenharmony_ci// instruction using the label. 4311cb0ef41Sopenharmony_ci 4321cb0ef41Sopenharmony_ci// The link chain is terminated by a value in the instruction of -1, 4331cb0ef41Sopenharmony_ci// which is an otherwise illegal value (branch -1 is inf loop). 4341cb0ef41Sopenharmony_ci// The instruction 16-bit offset field addresses 32-bit words, but in 4351cb0ef41Sopenharmony_ci// code is conv to an 18-bit value addressing bytes, hence the -4 value. 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ciconst int kEndOfChain = -4; 4381cb0ef41Sopenharmony_ci// Determines the end of the Jump chain (a subset of the label link chain). 4391cb0ef41Sopenharmony_ciconst int kEndOfJumpChain = 0; 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_cibool Assembler::IsMsaBranch(Instr instr) { 4421cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 4431cb0ef41Sopenharmony_ci uint32_t rs_field = GetRsField(instr); 4441cb0ef41Sopenharmony_ci if (opcode == COP1) { 4451cb0ef41Sopenharmony_ci switch (rs_field) { 4461cb0ef41Sopenharmony_ci case BZ_V: 4471cb0ef41Sopenharmony_ci case BZ_B: 4481cb0ef41Sopenharmony_ci case BZ_H: 4491cb0ef41Sopenharmony_ci case BZ_W: 4501cb0ef41Sopenharmony_ci case BZ_D: 4511cb0ef41Sopenharmony_ci case BNZ_V: 4521cb0ef41Sopenharmony_ci case BNZ_B: 4531cb0ef41Sopenharmony_ci case BNZ_H: 4541cb0ef41Sopenharmony_ci case BNZ_W: 4551cb0ef41Sopenharmony_ci case BNZ_D: 4561cb0ef41Sopenharmony_ci return true; 4571cb0ef41Sopenharmony_ci default: 4581cb0ef41Sopenharmony_ci return false; 4591cb0ef41Sopenharmony_ci } 4601cb0ef41Sopenharmony_ci } else { 4611cb0ef41Sopenharmony_ci return false; 4621cb0ef41Sopenharmony_ci } 4631cb0ef41Sopenharmony_ci} 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_cibool Assembler::IsBranch(Instr instr) { 4661cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 4671cb0ef41Sopenharmony_ci uint32_t rt_field = GetRtField(instr); 4681cb0ef41Sopenharmony_ci uint32_t rs_field = GetRsField(instr); 4691cb0ef41Sopenharmony_ci // Checks if the instruction is a branch. 4701cb0ef41Sopenharmony_ci bool isBranch = 4711cb0ef41Sopenharmony_ci opcode == BEQ || opcode == BNE || opcode == BLEZ || opcode == BGTZ || 4721cb0ef41Sopenharmony_ci opcode == BEQL || opcode == BNEL || opcode == BLEZL || opcode == BGTZL || 4731cb0ef41Sopenharmony_ci (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || 4741cb0ef41Sopenharmony_ci rt_field == BLTZAL || rt_field == BGEZAL)) || 4751cb0ef41Sopenharmony_ci (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. 4761cb0ef41Sopenharmony_ci (opcode == COP1 && rs_field == BC1EQZ) || 4771cb0ef41Sopenharmony_ci (opcode == COP1 && rs_field == BC1NEZ) || IsMsaBranch(instr); 4781cb0ef41Sopenharmony_ci if (!isBranch && kArchVariant == kMips64r6) { 4791cb0ef41Sopenharmony_ci // All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and 4801cb0ef41Sopenharmony_ci // POP30 (BNVC, BNEC, BNEZALC) are branch ops. 4811cb0ef41Sopenharmony_ci isBranch |= opcode == POP10 || opcode == POP30 || opcode == BC || 4821cb0ef41Sopenharmony_ci opcode == BALC || 4831cb0ef41Sopenharmony_ci (opcode == POP66 && rs_field != 0) || // BEQZC 4841cb0ef41Sopenharmony_ci (opcode == POP76 && rs_field != 0); // BNEZC 4851cb0ef41Sopenharmony_ci } 4861cb0ef41Sopenharmony_ci return isBranch; 4871cb0ef41Sopenharmony_ci} 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_cibool Assembler::IsBc(Instr instr) { 4901cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 4911cb0ef41Sopenharmony_ci // Checks if the instruction is a BC or BALC. 4921cb0ef41Sopenharmony_ci return opcode == BC || opcode == BALC; 4931cb0ef41Sopenharmony_ci} 4941cb0ef41Sopenharmony_ci 4951cb0ef41Sopenharmony_cibool Assembler::IsNal(Instr instr) { 4961cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 4971cb0ef41Sopenharmony_ci uint32_t rt_field = GetRtField(instr); 4981cb0ef41Sopenharmony_ci uint32_t rs_field = GetRsField(instr); 4991cb0ef41Sopenharmony_ci return opcode == REGIMM && rt_field == BLTZAL && rs_field == 0; 5001cb0ef41Sopenharmony_ci} 5011cb0ef41Sopenharmony_ci 5021cb0ef41Sopenharmony_cibool Assembler::IsBzc(Instr instr) { 5031cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 5041cb0ef41Sopenharmony_ci // Checks if the instruction is BEQZC or BNEZC. 5051cb0ef41Sopenharmony_ci return (opcode == POP66 && GetRsField(instr) != 0) || 5061cb0ef41Sopenharmony_ci (opcode == POP76 && GetRsField(instr) != 0); 5071cb0ef41Sopenharmony_ci} 5081cb0ef41Sopenharmony_ci 5091cb0ef41Sopenharmony_cibool Assembler::IsEmittedConstant(Instr instr) { 5101cb0ef41Sopenharmony_ci uint32_t label_constant = GetLabelConst(instr); 5111cb0ef41Sopenharmony_ci return label_constant == 0; // Emitted label const in reg-exp engine. 5121cb0ef41Sopenharmony_ci} 5131cb0ef41Sopenharmony_ci 5141cb0ef41Sopenharmony_cibool Assembler::IsBeq(Instr instr) { return GetOpcodeField(instr) == BEQ; } 5151cb0ef41Sopenharmony_ci 5161cb0ef41Sopenharmony_cibool Assembler::IsBne(Instr instr) { return GetOpcodeField(instr) == BNE; } 5171cb0ef41Sopenharmony_ci 5181cb0ef41Sopenharmony_cibool Assembler::IsBeqzc(Instr instr) { 5191cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 5201cb0ef41Sopenharmony_ci return opcode == POP66 && GetRsField(instr) != 0; 5211cb0ef41Sopenharmony_ci} 5221cb0ef41Sopenharmony_ci 5231cb0ef41Sopenharmony_cibool Assembler::IsBnezc(Instr instr) { 5241cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 5251cb0ef41Sopenharmony_ci return opcode == POP76 && GetRsField(instr) != 0; 5261cb0ef41Sopenharmony_ci} 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_cibool Assembler::IsBeqc(Instr instr) { 5291cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 5301cb0ef41Sopenharmony_ci uint32_t rs = GetRsField(instr); 5311cb0ef41Sopenharmony_ci uint32_t rt = GetRtField(instr); 5321cb0ef41Sopenharmony_ci return opcode == POP10 && rs != 0 && rs < rt; // && rt != 0 5331cb0ef41Sopenharmony_ci} 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_cibool Assembler::IsBnec(Instr instr) { 5361cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 5371cb0ef41Sopenharmony_ci uint32_t rs = GetRsField(instr); 5381cb0ef41Sopenharmony_ci uint32_t rt = GetRtField(instr); 5391cb0ef41Sopenharmony_ci return opcode == POP30 && rs != 0 && rs < rt; // && rt != 0 5401cb0ef41Sopenharmony_ci} 5411cb0ef41Sopenharmony_ci 5421cb0ef41Sopenharmony_cibool Assembler::IsMov(Instr instr, Register rd, Register rs) { 5431cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 5441cb0ef41Sopenharmony_ci uint32_t rd_field = GetRd(instr); 5451cb0ef41Sopenharmony_ci uint32_t rs_field = GetRs(instr); 5461cb0ef41Sopenharmony_ci uint32_t rt_field = GetRt(instr); 5471cb0ef41Sopenharmony_ci uint32_t rd_reg = static_cast<uint32_t>(rd.code()); 5481cb0ef41Sopenharmony_ci uint32_t rs_reg = static_cast<uint32_t>(rs.code()); 5491cb0ef41Sopenharmony_ci uint32_t function_field = GetFunctionField(instr); 5501cb0ef41Sopenharmony_ci // Checks if the instruction is a OR with zero_reg argument (aka MOV). 5511cb0ef41Sopenharmony_ci bool res = opcode == SPECIAL && function_field == OR && rd_field == rd_reg && 5521cb0ef41Sopenharmony_ci rs_field == rs_reg && rt_field == 0; 5531cb0ef41Sopenharmony_ci return res; 5541cb0ef41Sopenharmony_ci} 5551cb0ef41Sopenharmony_ci 5561cb0ef41Sopenharmony_cibool Assembler::IsJump(Instr instr) { 5571cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 5581cb0ef41Sopenharmony_ci uint32_t rt_field = GetRtField(instr); 5591cb0ef41Sopenharmony_ci uint32_t rd_field = GetRdField(instr); 5601cb0ef41Sopenharmony_ci uint32_t function_field = GetFunctionField(instr); 5611cb0ef41Sopenharmony_ci // Checks if the instruction is a jump. 5621cb0ef41Sopenharmony_ci return opcode == J || opcode == JAL || 5631cb0ef41Sopenharmony_ci (opcode == SPECIAL && rt_field == 0 && 5641cb0ef41Sopenharmony_ci ((function_field == JALR) || 5651cb0ef41Sopenharmony_ci (rd_field == 0 && (function_field == JR)))); 5661cb0ef41Sopenharmony_ci} 5671cb0ef41Sopenharmony_ci 5681cb0ef41Sopenharmony_cibool Assembler::IsJ(Instr instr) { 5691cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 5701cb0ef41Sopenharmony_ci // Checks if the instruction is a jump. 5711cb0ef41Sopenharmony_ci return opcode == J; 5721cb0ef41Sopenharmony_ci} 5731cb0ef41Sopenharmony_ci 5741cb0ef41Sopenharmony_cibool Assembler::IsJal(Instr instr) { return GetOpcodeField(instr) == JAL; } 5751cb0ef41Sopenharmony_ci 5761cb0ef41Sopenharmony_cibool Assembler::IsJr(Instr instr) { 5771cb0ef41Sopenharmony_ci return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR; 5781cb0ef41Sopenharmony_ci} 5791cb0ef41Sopenharmony_ci 5801cb0ef41Sopenharmony_cibool Assembler::IsJalr(Instr instr) { 5811cb0ef41Sopenharmony_ci return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JALR; 5821cb0ef41Sopenharmony_ci} 5831cb0ef41Sopenharmony_ci 5841cb0ef41Sopenharmony_cibool Assembler::IsLui(Instr instr) { 5851cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 5861cb0ef41Sopenharmony_ci // Checks if the instruction is a load upper immediate. 5871cb0ef41Sopenharmony_ci return opcode == LUI; 5881cb0ef41Sopenharmony_ci} 5891cb0ef41Sopenharmony_ci 5901cb0ef41Sopenharmony_cibool Assembler::IsOri(Instr instr) { 5911cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 5921cb0ef41Sopenharmony_ci // Checks if the instruction is a load upper immediate. 5931cb0ef41Sopenharmony_ci return opcode == ORI; 5941cb0ef41Sopenharmony_ci} 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_cibool Assembler::IsNop(Instr instr, unsigned int type) { 5971cb0ef41Sopenharmony_ci // See Assembler::nop(type). 5981cb0ef41Sopenharmony_ci DCHECK_LT(type, 32); 5991cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 6001cb0ef41Sopenharmony_ci uint32_t function = GetFunctionField(instr); 6011cb0ef41Sopenharmony_ci uint32_t rt = GetRt(instr); 6021cb0ef41Sopenharmony_ci uint32_t rd = GetRd(instr); 6031cb0ef41Sopenharmony_ci uint32_t sa = GetSa(instr); 6041cb0ef41Sopenharmony_ci 6051cb0ef41Sopenharmony_ci // Traditional mips nop == sll(zero_reg, zero_reg, 0) 6061cb0ef41Sopenharmony_ci // When marking non-zero type, use sll(zero_reg, at, type) 6071cb0ef41Sopenharmony_ci // to avoid use of mips ssnop and ehb special encodings 6081cb0ef41Sopenharmony_ci // of the sll instruction. 6091cb0ef41Sopenharmony_ci 6101cb0ef41Sopenharmony_ci Register nop_rt_reg = (type == 0) ? zero_reg : at; 6111cb0ef41Sopenharmony_ci bool ret = (opcode == SPECIAL && function == SLL && 6121cb0ef41Sopenharmony_ci rd == static_cast<uint32_t>(ToNumber(zero_reg)) && 6131cb0ef41Sopenharmony_ci rt == static_cast<uint32_t>(ToNumber(nop_rt_reg)) && sa == type); 6141cb0ef41Sopenharmony_ci 6151cb0ef41Sopenharmony_ci return ret; 6161cb0ef41Sopenharmony_ci} 6171cb0ef41Sopenharmony_ci 6181cb0ef41Sopenharmony_ciint32_t Assembler::GetBranchOffset(Instr instr) { 6191cb0ef41Sopenharmony_ci DCHECK(IsBranch(instr)); 6201cb0ef41Sopenharmony_ci return (static_cast<int16_t>(instr & kImm16Mask)) << 2; 6211cb0ef41Sopenharmony_ci} 6221cb0ef41Sopenharmony_ci 6231cb0ef41Sopenharmony_cibool Assembler::IsLw(Instr instr) { 6241cb0ef41Sopenharmony_ci return (static_cast<uint32_t>(instr & kOpcodeMask) == LW); 6251cb0ef41Sopenharmony_ci} 6261cb0ef41Sopenharmony_ci 6271cb0ef41Sopenharmony_ciint16_t Assembler::GetLwOffset(Instr instr) { 6281cb0ef41Sopenharmony_ci DCHECK(IsLw(instr)); 6291cb0ef41Sopenharmony_ci return ((instr & kImm16Mask)); 6301cb0ef41Sopenharmony_ci} 6311cb0ef41Sopenharmony_ci 6321cb0ef41Sopenharmony_ciInstr Assembler::SetLwOffset(Instr instr, int16_t offset) { 6331cb0ef41Sopenharmony_ci DCHECK(IsLw(instr)); 6341cb0ef41Sopenharmony_ci 6351cb0ef41Sopenharmony_ci // We actually create a new lw instruction based on the original one. 6361cb0ef41Sopenharmony_ci Instr temp_instr = LW | (instr & kRsFieldMask) | (instr & kRtFieldMask) | 6371cb0ef41Sopenharmony_ci (offset & kImm16Mask); 6381cb0ef41Sopenharmony_ci 6391cb0ef41Sopenharmony_ci return temp_instr; 6401cb0ef41Sopenharmony_ci} 6411cb0ef41Sopenharmony_ci 6421cb0ef41Sopenharmony_cibool Assembler::IsSw(Instr instr) { 6431cb0ef41Sopenharmony_ci return (static_cast<uint32_t>(instr & kOpcodeMask) == SW); 6441cb0ef41Sopenharmony_ci} 6451cb0ef41Sopenharmony_ci 6461cb0ef41Sopenharmony_ciInstr Assembler::SetSwOffset(Instr instr, int16_t offset) { 6471cb0ef41Sopenharmony_ci DCHECK(IsSw(instr)); 6481cb0ef41Sopenharmony_ci return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); 6491cb0ef41Sopenharmony_ci} 6501cb0ef41Sopenharmony_ci 6511cb0ef41Sopenharmony_cibool Assembler::IsAddImmediate(Instr instr) { 6521cb0ef41Sopenharmony_ci return ((instr & kOpcodeMask) == ADDIU || (instr & kOpcodeMask) == DADDIU); 6531cb0ef41Sopenharmony_ci} 6541cb0ef41Sopenharmony_ci 6551cb0ef41Sopenharmony_ciInstr Assembler::SetAddImmediateOffset(Instr instr, int16_t offset) { 6561cb0ef41Sopenharmony_ci DCHECK(IsAddImmediate(instr)); 6571cb0ef41Sopenharmony_ci return ((instr & ~kImm16Mask) | (offset & kImm16Mask)); 6581cb0ef41Sopenharmony_ci} 6591cb0ef41Sopenharmony_ci 6601cb0ef41Sopenharmony_cibool Assembler::IsAndImmediate(Instr instr) { 6611cb0ef41Sopenharmony_ci return GetOpcodeField(instr) == ANDI; 6621cb0ef41Sopenharmony_ci} 6631cb0ef41Sopenharmony_ci 6641cb0ef41Sopenharmony_cistatic Assembler::OffsetSize OffsetSizeInBits(Instr instr) { 6651cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 6661cb0ef41Sopenharmony_ci if (Assembler::IsBc(instr)) { 6671cb0ef41Sopenharmony_ci return Assembler::OffsetSize::kOffset26; 6681cb0ef41Sopenharmony_ci } else if (Assembler::IsBzc(instr)) { 6691cb0ef41Sopenharmony_ci return Assembler::OffsetSize::kOffset21; 6701cb0ef41Sopenharmony_ci } 6711cb0ef41Sopenharmony_ci } 6721cb0ef41Sopenharmony_ci return Assembler::OffsetSize::kOffset16; 6731cb0ef41Sopenharmony_ci} 6741cb0ef41Sopenharmony_ci 6751cb0ef41Sopenharmony_cistatic inline int32_t AddBranchOffset(int pos, Instr instr) { 6761cb0ef41Sopenharmony_ci int bits = OffsetSizeInBits(instr); 6771cb0ef41Sopenharmony_ci const int32_t mask = (1 << bits) - 1; 6781cb0ef41Sopenharmony_ci bits = 32 - bits; 6791cb0ef41Sopenharmony_ci 6801cb0ef41Sopenharmony_ci // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming 6811cb0ef41Sopenharmony_ci // the compiler uses arithmetic shifts for signed integers. 6821cb0ef41Sopenharmony_ci int32_t imm = ((instr & mask) << bits) >> (bits - 2); 6831cb0ef41Sopenharmony_ci 6841cb0ef41Sopenharmony_ci if (imm == kEndOfChain) { 6851cb0ef41Sopenharmony_ci // EndOfChain sentinel is returned directly, not relative to pc or pos. 6861cb0ef41Sopenharmony_ci return kEndOfChain; 6871cb0ef41Sopenharmony_ci } else { 6881cb0ef41Sopenharmony_ci return pos + Assembler::kBranchPCOffset + imm; 6891cb0ef41Sopenharmony_ci } 6901cb0ef41Sopenharmony_ci} 6911cb0ef41Sopenharmony_ci 6921cb0ef41Sopenharmony_ciint Assembler::target_at(int pos, bool is_internal) { 6931cb0ef41Sopenharmony_ci if (is_internal) { 6941cb0ef41Sopenharmony_ci int64_t* p = reinterpret_cast<int64_t*>(buffer_start_ + pos); 6951cb0ef41Sopenharmony_ci int64_t address = *p; 6961cb0ef41Sopenharmony_ci if (address == kEndOfJumpChain) { 6971cb0ef41Sopenharmony_ci return kEndOfChain; 6981cb0ef41Sopenharmony_ci } else { 6991cb0ef41Sopenharmony_ci int64_t instr_address = reinterpret_cast<int64_t>(p); 7001cb0ef41Sopenharmony_ci DCHECK(instr_address - address < INT_MAX); 7011cb0ef41Sopenharmony_ci int delta = static_cast<int>(instr_address - address); 7021cb0ef41Sopenharmony_ci DCHECK(pos > delta); 7031cb0ef41Sopenharmony_ci return pos - delta; 7041cb0ef41Sopenharmony_ci } 7051cb0ef41Sopenharmony_ci } 7061cb0ef41Sopenharmony_ci Instr instr = instr_at(pos); 7071cb0ef41Sopenharmony_ci if ((instr & ~kImm16Mask) == 0) { 7081cb0ef41Sopenharmony_ci // Emitted label constant, not part of a branch. 7091cb0ef41Sopenharmony_ci if (instr == 0) { 7101cb0ef41Sopenharmony_ci return kEndOfChain; 7111cb0ef41Sopenharmony_ci } else { 7121cb0ef41Sopenharmony_ci int32_t imm18 = ((instr & static_cast<int32_t>(kImm16Mask)) << 16) >> 14; 7131cb0ef41Sopenharmony_ci return (imm18 + pos); 7141cb0ef41Sopenharmony_ci } 7151cb0ef41Sopenharmony_ci } 7161cb0ef41Sopenharmony_ci // Check we have a branch or jump instruction. 7171cb0ef41Sopenharmony_ci DCHECK(IsBranch(instr) || IsJ(instr) || IsJal(instr) || IsLui(instr) || 7181cb0ef41Sopenharmony_ci IsMov(instr, t8, ra)); 7191cb0ef41Sopenharmony_ci // Do NOT change this to <<2. We rely on arithmetic shifts here, assuming 7201cb0ef41Sopenharmony_ci // the compiler uses arithmetic shifts for signed integers. 7211cb0ef41Sopenharmony_ci if (IsBranch(instr)) { 7221cb0ef41Sopenharmony_ci return AddBranchOffset(pos, instr); 7231cb0ef41Sopenharmony_ci } else if (IsMov(instr, t8, ra)) { 7241cb0ef41Sopenharmony_ci int32_t imm32; 7251cb0ef41Sopenharmony_ci Instr instr_lui = instr_at(pos + 2 * kInstrSize); 7261cb0ef41Sopenharmony_ci Instr instr_ori = instr_at(pos + 3 * kInstrSize); 7271cb0ef41Sopenharmony_ci DCHECK(IsLui(instr_lui)); 7281cb0ef41Sopenharmony_ci DCHECK(IsOri(instr_ori)); 7291cb0ef41Sopenharmony_ci imm32 = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; 7301cb0ef41Sopenharmony_ci imm32 |= (instr_ori & static_cast<int32_t>(kImm16Mask)); 7311cb0ef41Sopenharmony_ci if (imm32 == kEndOfJumpChain) { 7321cb0ef41Sopenharmony_ci // EndOfChain sentinel is returned directly, not relative to pc or pos. 7331cb0ef41Sopenharmony_ci return kEndOfChain; 7341cb0ef41Sopenharmony_ci } 7351cb0ef41Sopenharmony_ci return pos + Assembler::kLongBranchPCOffset + imm32; 7361cb0ef41Sopenharmony_ci } else if (IsLui(instr)) { 7371cb0ef41Sopenharmony_ci if (IsNal(instr_at(pos + kInstrSize))) { 7381cb0ef41Sopenharmony_ci int32_t imm32; 7391cb0ef41Sopenharmony_ci Instr instr_lui = instr_at(pos + 0 * kInstrSize); 7401cb0ef41Sopenharmony_ci Instr instr_ori = instr_at(pos + 2 * kInstrSize); 7411cb0ef41Sopenharmony_ci DCHECK(IsLui(instr_lui)); 7421cb0ef41Sopenharmony_ci DCHECK(IsOri(instr_ori)); 7431cb0ef41Sopenharmony_ci imm32 = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift; 7441cb0ef41Sopenharmony_ci imm32 |= (instr_ori & static_cast<int32_t>(kImm16Mask)); 7451cb0ef41Sopenharmony_ci if (imm32 == kEndOfJumpChain) { 7461cb0ef41Sopenharmony_ci // EndOfChain sentinel is returned directly, not relative to pc or pos. 7471cb0ef41Sopenharmony_ci return kEndOfChain; 7481cb0ef41Sopenharmony_ci } 7491cb0ef41Sopenharmony_ci return pos + Assembler::kLongBranchPCOffset + imm32; 7501cb0ef41Sopenharmony_ci } else { 7511cb0ef41Sopenharmony_ci Instr instr_lui = instr_at(pos + 0 * kInstrSize); 7521cb0ef41Sopenharmony_ci Instr instr_ori = instr_at(pos + 1 * kInstrSize); 7531cb0ef41Sopenharmony_ci Instr instr_ori2 = instr_at(pos + 3 * kInstrSize); 7541cb0ef41Sopenharmony_ci DCHECK(IsOri(instr_ori)); 7551cb0ef41Sopenharmony_ci DCHECK(IsOri(instr_ori2)); 7561cb0ef41Sopenharmony_ci 7571cb0ef41Sopenharmony_ci // TODO(plind) create named constants for shift values. 7581cb0ef41Sopenharmony_ci int64_t imm = static_cast<int64_t>(instr_lui & kImm16Mask) << 48; 7591cb0ef41Sopenharmony_ci imm |= static_cast<int64_t>(instr_ori & kImm16Mask) << 32; 7601cb0ef41Sopenharmony_ci imm |= static_cast<int64_t>(instr_ori2 & kImm16Mask) << 16; 7611cb0ef41Sopenharmony_ci // Sign extend address; 7621cb0ef41Sopenharmony_ci imm >>= 16; 7631cb0ef41Sopenharmony_ci 7641cb0ef41Sopenharmony_ci if (imm == kEndOfJumpChain) { 7651cb0ef41Sopenharmony_ci // EndOfChain sentinel is returned directly, not relative to pc or pos. 7661cb0ef41Sopenharmony_ci return kEndOfChain; 7671cb0ef41Sopenharmony_ci } else { 7681cb0ef41Sopenharmony_ci uint64_t instr_address = reinterpret_cast<int64_t>(buffer_start_ + pos); 7691cb0ef41Sopenharmony_ci DCHECK(instr_address - imm < INT_MAX); 7701cb0ef41Sopenharmony_ci int delta = static_cast<int>(instr_address - imm); 7711cb0ef41Sopenharmony_ci DCHECK(pos > delta); 7721cb0ef41Sopenharmony_ci return pos - delta; 7731cb0ef41Sopenharmony_ci } 7741cb0ef41Sopenharmony_ci } 7751cb0ef41Sopenharmony_ci } else { 7761cb0ef41Sopenharmony_ci DCHECK(IsJ(instr) || IsJal(instr)); 7771cb0ef41Sopenharmony_ci int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; 7781cb0ef41Sopenharmony_ci if (imm28 == kEndOfJumpChain) { 7791cb0ef41Sopenharmony_ci // EndOfChain sentinel is returned directly, not relative to pc or pos. 7801cb0ef41Sopenharmony_ci return kEndOfChain; 7811cb0ef41Sopenharmony_ci } else { 7821cb0ef41Sopenharmony_ci // Sign extend 28-bit offset. 7831cb0ef41Sopenharmony_ci int32_t delta = static_cast<int32_t>((imm28 << 4) >> 4); 7841cb0ef41Sopenharmony_ci return pos + delta; 7851cb0ef41Sopenharmony_ci } 7861cb0ef41Sopenharmony_ci } 7871cb0ef41Sopenharmony_ci} 7881cb0ef41Sopenharmony_ci 7891cb0ef41Sopenharmony_cistatic inline Instr SetBranchOffset(int32_t pos, int32_t target_pos, 7901cb0ef41Sopenharmony_ci Instr instr) { 7911cb0ef41Sopenharmony_ci int32_t bits = OffsetSizeInBits(instr); 7921cb0ef41Sopenharmony_ci int32_t imm = target_pos - (pos + Assembler::kBranchPCOffset); 7931cb0ef41Sopenharmony_ci DCHECK_EQ(imm & 3, 0); 7941cb0ef41Sopenharmony_ci imm >>= 2; 7951cb0ef41Sopenharmony_ci 7961cb0ef41Sopenharmony_ci const int32_t mask = (1 << bits) - 1; 7971cb0ef41Sopenharmony_ci instr &= ~mask; 7981cb0ef41Sopenharmony_ci DCHECK(is_intn(imm, bits)); 7991cb0ef41Sopenharmony_ci 8001cb0ef41Sopenharmony_ci return instr | (imm & mask); 8011cb0ef41Sopenharmony_ci} 8021cb0ef41Sopenharmony_ci 8031cb0ef41Sopenharmony_civoid Assembler::target_at_put(int pos, int target_pos, bool is_internal) { 8041cb0ef41Sopenharmony_ci if (is_internal) { 8051cb0ef41Sopenharmony_ci uint64_t imm = reinterpret_cast<uint64_t>(buffer_start_) + target_pos; 8061cb0ef41Sopenharmony_ci *reinterpret_cast<uint64_t*>(buffer_start_ + pos) = imm; 8071cb0ef41Sopenharmony_ci return; 8081cb0ef41Sopenharmony_ci } 8091cb0ef41Sopenharmony_ci Instr instr = instr_at(pos); 8101cb0ef41Sopenharmony_ci if ((instr & ~kImm16Mask) == 0) { 8111cb0ef41Sopenharmony_ci DCHECK(target_pos == kEndOfChain || target_pos >= 0); 8121cb0ef41Sopenharmony_ci // Emitted label constant, not part of a branch. 8131cb0ef41Sopenharmony_ci // Make label relative to Code pointer of generated Code object. 8141cb0ef41Sopenharmony_ci instr_at_put(pos, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 8151cb0ef41Sopenharmony_ci return; 8161cb0ef41Sopenharmony_ci } 8171cb0ef41Sopenharmony_ci 8181cb0ef41Sopenharmony_ci if (IsBranch(instr)) { 8191cb0ef41Sopenharmony_ci instr = SetBranchOffset(pos, target_pos, instr); 8201cb0ef41Sopenharmony_ci instr_at_put(pos, instr); 8211cb0ef41Sopenharmony_ci } else if (IsLui(instr)) { 8221cb0ef41Sopenharmony_ci if (IsNal(instr_at(pos + kInstrSize))) { 8231cb0ef41Sopenharmony_ci Instr instr_lui = instr_at(pos + 0 * kInstrSize); 8241cb0ef41Sopenharmony_ci Instr instr_ori = instr_at(pos + 2 * kInstrSize); 8251cb0ef41Sopenharmony_ci DCHECK(IsLui(instr_lui)); 8261cb0ef41Sopenharmony_ci DCHECK(IsOri(instr_ori)); 8271cb0ef41Sopenharmony_ci int32_t imm = target_pos - (pos + Assembler::kLongBranchPCOffset); 8281cb0ef41Sopenharmony_ci DCHECK_EQ(imm & 3, 0); 8291cb0ef41Sopenharmony_ci if (is_int16(imm + Assembler::kLongBranchPCOffset - 8301cb0ef41Sopenharmony_ci Assembler::kBranchPCOffset)) { 8311cb0ef41Sopenharmony_ci // Optimize by converting to regular branch and link with 16-bit 8321cb0ef41Sopenharmony_ci // offset. 8331cb0ef41Sopenharmony_ci Instr instr_b = REGIMM | BGEZAL; // Branch and link. 8341cb0ef41Sopenharmony_ci instr_b = SetBranchOffset(pos, target_pos, instr_b); 8351cb0ef41Sopenharmony_ci // Correct ra register to point to one instruction after jalr from 8361cb0ef41Sopenharmony_ci // TurboAssembler::BranchAndLinkLong. 8371cb0ef41Sopenharmony_ci Instr instr_a = DADDIU | ra.code() << kRsShift | ra.code() << kRtShift | 8381cb0ef41Sopenharmony_ci kOptimizedBranchAndLinkLongReturnOffset; 8391cb0ef41Sopenharmony_ci 8401cb0ef41Sopenharmony_ci instr_at_put(pos, instr_b); 8411cb0ef41Sopenharmony_ci instr_at_put(pos + 1 * kInstrSize, instr_a); 8421cb0ef41Sopenharmony_ci } else { 8431cb0ef41Sopenharmony_ci instr_lui &= ~kImm16Mask; 8441cb0ef41Sopenharmony_ci instr_ori &= ~kImm16Mask; 8451cb0ef41Sopenharmony_ci 8461cb0ef41Sopenharmony_ci instr_at_put(pos + 0 * kInstrSize, 8471cb0ef41Sopenharmony_ci instr_lui | ((imm >> kLuiShift) & kImm16Mask)); 8481cb0ef41Sopenharmony_ci instr_at_put(pos + 2 * kInstrSize, instr_ori | (imm & kImm16Mask)); 8491cb0ef41Sopenharmony_ci } 8501cb0ef41Sopenharmony_ci } else { 8511cb0ef41Sopenharmony_ci Instr instr_lui = instr_at(pos + 0 * kInstrSize); 8521cb0ef41Sopenharmony_ci Instr instr_ori = instr_at(pos + 1 * kInstrSize); 8531cb0ef41Sopenharmony_ci Instr instr_ori2 = instr_at(pos + 3 * kInstrSize); 8541cb0ef41Sopenharmony_ci DCHECK(IsOri(instr_ori)); 8551cb0ef41Sopenharmony_ci DCHECK(IsOri(instr_ori2)); 8561cb0ef41Sopenharmony_ci 8571cb0ef41Sopenharmony_ci uint64_t imm = reinterpret_cast<uint64_t>(buffer_start_) + target_pos; 8581cb0ef41Sopenharmony_ci DCHECK_EQ(imm & 3, 0); 8591cb0ef41Sopenharmony_ci 8601cb0ef41Sopenharmony_ci instr_lui &= ~kImm16Mask; 8611cb0ef41Sopenharmony_ci instr_ori &= ~kImm16Mask; 8621cb0ef41Sopenharmony_ci instr_ori2 &= ~kImm16Mask; 8631cb0ef41Sopenharmony_ci 8641cb0ef41Sopenharmony_ci instr_at_put(pos + 0 * kInstrSize, 8651cb0ef41Sopenharmony_ci instr_lui | ((imm >> 32) & kImm16Mask)); 8661cb0ef41Sopenharmony_ci instr_at_put(pos + 1 * kInstrSize, 8671cb0ef41Sopenharmony_ci instr_ori | ((imm >> 16) & kImm16Mask)); 8681cb0ef41Sopenharmony_ci instr_at_put(pos + 3 * kInstrSize, instr_ori2 | (imm & kImm16Mask)); 8691cb0ef41Sopenharmony_ci } 8701cb0ef41Sopenharmony_ci } else if (IsMov(instr, t8, ra)) { 8711cb0ef41Sopenharmony_ci Instr instr_lui = instr_at(pos + 2 * kInstrSize); 8721cb0ef41Sopenharmony_ci Instr instr_ori = instr_at(pos + 3 * kInstrSize); 8731cb0ef41Sopenharmony_ci DCHECK(IsLui(instr_lui)); 8741cb0ef41Sopenharmony_ci DCHECK(IsOri(instr_ori)); 8751cb0ef41Sopenharmony_ci 8761cb0ef41Sopenharmony_ci int32_t imm_short = target_pos - (pos + Assembler::kBranchPCOffset); 8771cb0ef41Sopenharmony_ci 8781cb0ef41Sopenharmony_ci if (is_int16(imm_short)) { 8791cb0ef41Sopenharmony_ci // Optimize by converting to regular branch with 16-bit 8801cb0ef41Sopenharmony_ci // offset 8811cb0ef41Sopenharmony_ci Instr instr_b = BEQ; 8821cb0ef41Sopenharmony_ci instr_b = SetBranchOffset(pos, target_pos, instr_b); 8831cb0ef41Sopenharmony_ci 8841cb0ef41Sopenharmony_ci Instr instr_j = instr_at(pos + 5 * kInstrSize); 8851cb0ef41Sopenharmony_ci Instr instr_branch_delay; 8861cb0ef41Sopenharmony_ci 8871cb0ef41Sopenharmony_ci if (IsJump(instr_j)) { 8881cb0ef41Sopenharmony_ci // Case when branch delay slot is protected. 8891cb0ef41Sopenharmony_ci instr_branch_delay = nopInstr; 8901cb0ef41Sopenharmony_ci } else { 8911cb0ef41Sopenharmony_ci // Case when branch delay slot is used. 8921cb0ef41Sopenharmony_ci instr_branch_delay = instr_at(pos + 7 * kInstrSize); 8931cb0ef41Sopenharmony_ci } 8941cb0ef41Sopenharmony_ci instr_at_put(pos, instr_b); 8951cb0ef41Sopenharmony_ci instr_at_put(pos + 1 * kInstrSize, instr_branch_delay); 8961cb0ef41Sopenharmony_ci } else { 8971cb0ef41Sopenharmony_ci int32_t imm = target_pos - (pos + Assembler::kLongBranchPCOffset); 8981cb0ef41Sopenharmony_ci DCHECK_EQ(imm & 3, 0); 8991cb0ef41Sopenharmony_ci 9001cb0ef41Sopenharmony_ci instr_lui &= ~kImm16Mask; 9011cb0ef41Sopenharmony_ci instr_ori &= ~kImm16Mask; 9021cb0ef41Sopenharmony_ci 9031cb0ef41Sopenharmony_ci instr_at_put(pos + 2 * kInstrSize, 9041cb0ef41Sopenharmony_ci instr_lui | ((imm >> kLuiShift) & kImm16Mask)); 9051cb0ef41Sopenharmony_ci instr_at_put(pos + 3 * kInstrSize, instr_ori | (imm & kImm16Mask)); 9061cb0ef41Sopenharmony_ci } 9071cb0ef41Sopenharmony_ci } else if (IsJ(instr) || IsJal(instr)) { 9081cb0ef41Sopenharmony_ci int32_t imm28 = target_pos - pos; 9091cb0ef41Sopenharmony_ci DCHECK_EQ(imm28 & 3, 0); 9101cb0ef41Sopenharmony_ci 9111cb0ef41Sopenharmony_ci uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2); 9121cb0ef41Sopenharmony_ci DCHECK(is_uint26(imm26)); 9131cb0ef41Sopenharmony_ci // Place 26-bit signed offset with markings. 9141cb0ef41Sopenharmony_ci // When code is committed it will be resolved to j/jal. 9151cb0ef41Sopenharmony_ci int32_t mark = IsJ(instr) ? kJRawMark : kJalRawMark; 9161cb0ef41Sopenharmony_ci instr_at_put(pos, mark | (imm26 & kImm26Mask)); 9171cb0ef41Sopenharmony_ci } else { 9181cb0ef41Sopenharmony_ci int32_t imm28 = target_pos - pos; 9191cb0ef41Sopenharmony_ci DCHECK_EQ(imm28 & 3, 0); 9201cb0ef41Sopenharmony_ci 9211cb0ef41Sopenharmony_ci uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2); 9221cb0ef41Sopenharmony_ci DCHECK(is_uint26(imm26)); 9231cb0ef41Sopenharmony_ci // Place raw 26-bit signed offset. 9241cb0ef41Sopenharmony_ci // When code is committed it will be resolved to j/jal. 9251cb0ef41Sopenharmony_ci instr &= ~kImm26Mask; 9261cb0ef41Sopenharmony_ci instr_at_put(pos, instr | (imm26 & kImm26Mask)); 9271cb0ef41Sopenharmony_ci } 9281cb0ef41Sopenharmony_ci} 9291cb0ef41Sopenharmony_ci 9301cb0ef41Sopenharmony_civoid Assembler::print(const Label* L) { 9311cb0ef41Sopenharmony_ci if (L->is_unused()) { 9321cb0ef41Sopenharmony_ci PrintF("unused label\n"); 9331cb0ef41Sopenharmony_ci } else if (L->is_bound()) { 9341cb0ef41Sopenharmony_ci PrintF("bound label to %d\n", L->pos()); 9351cb0ef41Sopenharmony_ci } else if (L->is_linked()) { 9361cb0ef41Sopenharmony_ci Label l; 9371cb0ef41Sopenharmony_ci l.link_to(L->pos()); 9381cb0ef41Sopenharmony_ci PrintF("unbound label"); 9391cb0ef41Sopenharmony_ci while (l.is_linked()) { 9401cb0ef41Sopenharmony_ci PrintF("@ %d ", l.pos()); 9411cb0ef41Sopenharmony_ci Instr instr = instr_at(l.pos()); 9421cb0ef41Sopenharmony_ci if ((instr & ~kImm16Mask) == 0) { 9431cb0ef41Sopenharmony_ci PrintF("value\n"); 9441cb0ef41Sopenharmony_ci } else { 9451cb0ef41Sopenharmony_ci PrintF("%d\n", instr); 9461cb0ef41Sopenharmony_ci } 9471cb0ef41Sopenharmony_ci next(&l, is_internal_reference(&l)); 9481cb0ef41Sopenharmony_ci } 9491cb0ef41Sopenharmony_ci } else { 9501cb0ef41Sopenharmony_ci PrintF("label in inconsistent state (pos = %d)\n", L->pos_); 9511cb0ef41Sopenharmony_ci } 9521cb0ef41Sopenharmony_ci} 9531cb0ef41Sopenharmony_ci 9541cb0ef41Sopenharmony_civoid Assembler::bind_to(Label* L, int pos) { 9551cb0ef41Sopenharmony_ci DCHECK(0 <= pos && pos <= pc_offset()); // Must have valid binding position. 9561cb0ef41Sopenharmony_ci int trampoline_pos = kInvalidSlotPos; 9571cb0ef41Sopenharmony_ci bool is_internal = false; 9581cb0ef41Sopenharmony_ci if (L->is_linked() && !trampoline_emitted_) { 9591cb0ef41Sopenharmony_ci unbound_labels_count_--; 9601cb0ef41Sopenharmony_ci if (!is_internal_reference(L)) { 9611cb0ef41Sopenharmony_ci next_buffer_check_ += kTrampolineSlotsSize; 9621cb0ef41Sopenharmony_ci } 9631cb0ef41Sopenharmony_ci } 9641cb0ef41Sopenharmony_ci 9651cb0ef41Sopenharmony_ci while (L->is_linked()) { 9661cb0ef41Sopenharmony_ci int fixup_pos = L->pos(); 9671cb0ef41Sopenharmony_ci int dist = pos - fixup_pos; 9681cb0ef41Sopenharmony_ci is_internal = is_internal_reference(L); 9691cb0ef41Sopenharmony_ci next(L, is_internal); // Call next before overwriting link with target at 9701cb0ef41Sopenharmony_ci // fixup_pos. 9711cb0ef41Sopenharmony_ci Instr instr = instr_at(fixup_pos); 9721cb0ef41Sopenharmony_ci if (is_internal) { 9731cb0ef41Sopenharmony_ci target_at_put(fixup_pos, pos, is_internal); 9741cb0ef41Sopenharmony_ci } else { 9751cb0ef41Sopenharmony_ci if (IsBranch(instr)) { 9761cb0ef41Sopenharmony_ci int branch_offset = BranchOffset(instr); 9771cb0ef41Sopenharmony_ci if (dist > branch_offset) { 9781cb0ef41Sopenharmony_ci if (trampoline_pos == kInvalidSlotPos) { 9791cb0ef41Sopenharmony_ci trampoline_pos = get_trampoline_entry(fixup_pos); 9801cb0ef41Sopenharmony_ci CHECK_NE(trampoline_pos, kInvalidSlotPos); 9811cb0ef41Sopenharmony_ci } 9821cb0ef41Sopenharmony_ci CHECK((trampoline_pos - fixup_pos) <= branch_offset); 9831cb0ef41Sopenharmony_ci target_at_put(fixup_pos, trampoline_pos, false); 9841cb0ef41Sopenharmony_ci fixup_pos = trampoline_pos; 9851cb0ef41Sopenharmony_ci } 9861cb0ef41Sopenharmony_ci target_at_put(fixup_pos, pos, false); 9871cb0ef41Sopenharmony_ci } else { 9881cb0ef41Sopenharmony_ci DCHECK(IsJ(instr) || IsJal(instr) || IsLui(instr) || 9891cb0ef41Sopenharmony_ci IsEmittedConstant(instr) || IsMov(instr, t8, ra)); 9901cb0ef41Sopenharmony_ci target_at_put(fixup_pos, pos, false); 9911cb0ef41Sopenharmony_ci } 9921cb0ef41Sopenharmony_ci } 9931cb0ef41Sopenharmony_ci } 9941cb0ef41Sopenharmony_ci L->bind_to(pos); 9951cb0ef41Sopenharmony_ci 9961cb0ef41Sopenharmony_ci // Keep track of the last bound label so we don't eliminate any instructions 9971cb0ef41Sopenharmony_ci // before a bound label. 9981cb0ef41Sopenharmony_ci if (pos > last_bound_pos_) last_bound_pos_ = pos; 9991cb0ef41Sopenharmony_ci} 10001cb0ef41Sopenharmony_ci 10011cb0ef41Sopenharmony_civoid Assembler::bind(Label* L) { 10021cb0ef41Sopenharmony_ci DCHECK(!L->is_bound()); // Label can only be bound once. 10031cb0ef41Sopenharmony_ci bind_to(L, pc_offset()); 10041cb0ef41Sopenharmony_ci} 10051cb0ef41Sopenharmony_ci 10061cb0ef41Sopenharmony_civoid Assembler::next(Label* L, bool is_internal) { 10071cb0ef41Sopenharmony_ci DCHECK(L->is_linked()); 10081cb0ef41Sopenharmony_ci int link = target_at(L->pos(), is_internal); 10091cb0ef41Sopenharmony_ci if (link == kEndOfChain) { 10101cb0ef41Sopenharmony_ci L->Unuse(); 10111cb0ef41Sopenharmony_ci } else { 10121cb0ef41Sopenharmony_ci DCHECK_GE(link, 0); 10131cb0ef41Sopenharmony_ci L->link_to(link); 10141cb0ef41Sopenharmony_ci } 10151cb0ef41Sopenharmony_ci} 10161cb0ef41Sopenharmony_ci 10171cb0ef41Sopenharmony_cibool Assembler::is_near(Label* L) { 10181cb0ef41Sopenharmony_ci DCHECK(L->is_bound()); 10191cb0ef41Sopenharmony_ci return pc_offset() - L->pos() < kMaxBranchOffset - 4 * kInstrSize; 10201cb0ef41Sopenharmony_ci} 10211cb0ef41Sopenharmony_ci 10221cb0ef41Sopenharmony_cibool Assembler::is_near(Label* L, OffsetSize bits) { 10231cb0ef41Sopenharmony_ci if (L == nullptr || !L->is_bound()) return true; 10241cb0ef41Sopenharmony_ci return ((pc_offset() - L->pos()) < 10251cb0ef41Sopenharmony_ci (1 << (bits + 2 - 1)) - 1 - 5 * kInstrSize); 10261cb0ef41Sopenharmony_ci} 10271cb0ef41Sopenharmony_ci 10281cb0ef41Sopenharmony_cibool Assembler::is_near_branch(Label* L) { 10291cb0ef41Sopenharmony_ci DCHECK(L->is_bound()); 10301cb0ef41Sopenharmony_ci return kArchVariant == kMips64r6 ? is_near_r6(L) : is_near_pre_r6(L); 10311cb0ef41Sopenharmony_ci} 10321cb0ef41Sopenharmony_ci 10331cb0ef41Sopenharmony_ciint Assembler::BranchOffset(Instr instr) { 10341cb0ef41Sopenharmony_ci // At pre-R6 and for other R6 branches the offset is 16 bits. 10351cb0ef41Sopenharmony_ci int bits = OffsetSize::kOffset16; 10361cb0ef41Sopenharmony_ci 10371cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 10381cb0ef41Sopenharmony_ci uint32_t opcode = GetOpcodeField(instr); 10391cb0ef41Sopenharmony_ci switch (opcode) { 10401cb0ef41Sopenharmony_ci // Checks BC or BALC. 10411cb0ef41Sopenharmony_ci case BC: 10421cb0ef41Sopenharmony_ci case BALC: 10431cb0ef41Sopenharmony_ci bits = OffsetSize::kOffset26; 10441cb0ef41Sopenharmony_ci break; 10451cb0ef41Sopenharmony_ci 10461cb0ef41Sopenharmony_ci // Checks BEQZC or BNEZC. 10471cb0ef41Sopenharmony_ci case POP66: 10481cb0ef41Sopenharmony_ci case POP76: 10491cb0ef41Sopenharmony_ci if (GetRsField(instr) != 0) bits = OffsetSize::kOffset21; 10501cb0ef41Sopenharmony_ci break; 10511cb0ef41Sopenharmony_ci default: 10521cb0ef41Sopenharmony_ci break; 10531cb0ef41Sopenharmony_ci } 10541cb0ef41Sopenharmony_ci } 10551cb0ef41Sopenharmony_ci 10561cb0ef41Sopenharmony_ci return (1 << (bits + 2 - 1)) - 1; 10571cb0ef41Sopenharmony_ci} 10581cb0ef41Sopenharmony_ci 10591cb0ef41Sopenharmony_ci// We have to use a temporary register for things that can be relocated even 10601cb0ef41Sopenharmony_ci// if they can be encoded in the MIPS's 16 bits of immediate-offset instruction 10611cb0ef41Sopenharmony_ci// space. There is no guarantee that the relocated location can be similarly 10621cb0ef41Sopenharmony_ci// encoded. 10631cb0ef41Sopenharmony_cibool Assembler::MustUseReg(RelocInfo::Mode rmode) { 10641cb0ef41Sopenharmony_ci return !RelocInfo::IsNoInfo(rmode); 10651cb0ef41Sopenharmony_ci} 10661cb0ef41Sopenharmony_ci 10671cb0ef41Sopenharmony_civoid Assembler::GenInstrRegister(Opcode opcode, Register rs, Register rt, 10681cb0ef41Sopenharmony_ci Register rd, uint16_t sa, 10691cb0ef41Sopenharmony_ci SecondaryField func) { 10701cb0ef41Sopenharmony_ci DCHECK(rd.is_valid() && rs.is_valid() && rt.is_valid() && is_uint5(sa)); 10711cb0ef41Sopenharmony_ci Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) | 10721cb0ef41Sopenharmony_ci (rd.code() << kRdShift) | (sa << kSaShift) | func; 10731cb0ef41Sopenharmony_ci emit(instr); 10741cb0ef41Sopenharmony_ci} 10751cb0ef41Sopenharmony_ci 10761cb0ef41Sopenharmony_civoid Assembler::GenInstrRegister(Opcode opcode, Register rs, Register rt, 10771cb0ef41Sopenharmony_ci uint16_t msb, uint16_t lsb, 10781cb0ef41Sopenharmony_ci SecondaryField func) { 10791cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && rt.is_valid() && is_uint5(msb) && is_uint5(lsb)); 10801cb0ef41Sopenharmony_ci Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) | 10811cb0ef41Sopenharmony_ci (msb << kRdShift) | (lsb << kSaShift) | func; 10821cb0ef41Sopenharmony_ci emit(instr); 10831cb0ef41Sopenharmony_ci} 10841cb0ef41Sopenharmony_ci 10851cb0ef41Sopenharmony_civoid Assembler::GenInstrRegister(Opcode opcode, SecondaryField fmt, 10861cb0ef41Sopenharmony_ci FPURegister ft, FPURegister fs, FPURegister fd, 10871cb0ef41Sopenharmony_ci SecondaryField func) { 10881cb0ef41Sopenharmony_ci DCHECK(fd.is_valid() && fs.is_valid() && ft.is_valid()); 10891cb0ef41Sopenharmony_ci Instr instr = opcode | fmt | (ft.code() << kFtShift) | 10901cb0ef41Sopenharmony_ci (fs.code() << kFsShift) | (fd.code() << kFdShift) | func; 10911cb0ef41Sopenharmony_ci emit(instr); 10921cb0ef41Sopenharmony_ci} 10931cb0ef41Sopenharmony_ci 10941cb0ef41Sopenharmony_civoid Assembler::GenInstrRegister(Opcode opcode, FPURegister fr, FPURegister ft, 10951cb0ef41Sopenharmony_ci FPURegister fs, FPURegister fd, 10961cb0ef41Sopenharmony_ci SecondaryField func) { 10971cb0ef41Sopenharmony_ci DCHECK(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid()); 10981cb0ef41Sopenharmony_ci Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift) | 10991cb0ef41Sopenharmony_ci (fs.code() << kFsShift) | (fd.code() << kFdShift) | func; 11001cb0ef41Sopenharmony_ci emit(instr); 11011cb0ef41Sopenharmony_ci} 11021cb0ef41Sopenharmony_ci 11031cb0ef41Sopenharmony_civoid Assembler::GenInstrRegister(Opcode opcode, SecondaryField fmt, Register rt, 11041cb0ef41Sopenharmony_ci FPURegister fs, FPURegister fd, 11051cb0ef41Sopenharmony_ci SecondaryField func) { 11061cb0ef41Sopenharmony_ci DCHECK(fd.is_valid() && fs.is_valid() && rt.is_valid()); 11071cb0ef41Sopenharmony_ci Instr instr = opcode | fmt | (rt.code() << kRtShift) | 11081cb0ef41Sopenharmony_ci (fs.code() << kFsShift) | (fd.code() << kFdShift) | func; 11091cb0ef41Sopenharmony_ci emit(instr); 11101cb0ef41Sopenharmony_ci} 11111cb0ef41Sopenharmony_ci 11121cb0ef41Sopenharmony_civoid Assembler::GenInstrRegister(Opcode opcode, SecondaryField fmt, Register rt, 11131cb0ef41Sopenharmony_ci FPUControlRegister fs, SecondaryField func) { 11141cb0ef41Sopenharmony_ci DCHECK(fs.is_valid() && rt.is_valid()); 11151cb0ef41Sopenharmony_ci Instr instr = 11161cb0ef41Sopenharmony_ci opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func; 11171cb0ef41Sopenharmony_ci emit(instr); 11181cb0ef41Sopenharmony_ci} 11191cb0ef41Sopenharmony_ci 11201cb0ef41Sopenharmony_ci// Instructions with immediate value. 11211cb0ef41Sopenharmony_ci// Registers are in the order of the instruction encoding, from left to right. 11221cb0ef41Sopenharmony_civoid Assembler::GenInstrImmediate(Opcode opcode, Register rs, Register rt, 11231cb0ef41Sopenharmony_ci int32_t j, 11241cb0ef41Sopenharmony_ci CompactBranchType is_compact_branch) { 11251cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && rt.is_valid() && (is_int16(j) || is_uint16(j))); 11261cb0ef41Sopenharmony_ci Instr instr = opcode | (rs.code() << kRsShift) | (rt.code() << kRtShift) | 11271cb0ef41Sopenharmony_ci (j & kImm16Mask); 11281cb0ef41Sopenharmony_ci emit(instr, is_compact_branch); 11291cb0ef41Sopenharmony_ci} 11301cb0ef41Sopenharmony_ci 11311cb0ef41Sopenharmony_civoid Assembler::GenInstrImmediate(Opcode opcode, Register base, Register rt, 11321cb0ef41Sopenharmony_ci int32_t offset9, int bit6, 11331cb0ef41Sopenharmony_ci SecondaryField func) { 11341cb0ef41Sopenharmony_ci DCHECK(base.is_valid() && rt.is_valid() && is_int9(offset9) && 11351cb0ef41Sopenharmony_ci is_uint1(bit6)); 11361cb0ef41Sopenharmony_ci Instr instr = opcode | (base.code() << kBaseShift) | (rt.code() << kRtShift) | 11371cb0ef41Sopenharmony_ci ((offset9 << kImm9Shift) & kImm9Mask) | bit6 << kBit6Shift | 11381cb0ef41Sopenharmony_ci func; 11391cb0ef41Sopenharmony_ci emit(instr); 11401cb0ef41Sopenharmony_ci} 11411cb0ef41Sopenharmony_ci 11421cb0ef41Sopenharmony_civoid Assembler::GenInstrImmediate(Opcode opcode, Register rs, SecondaryField SF, 11431cb0ef41Sopenharmony_ci int32_t j, 11441cb0ef41Sopenharmony_ci CompactBranchType is_compact_branch) { 11451cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && (is_int16(j) || is_uint16(j))); 11461cb0ef41Sopenharmony_ci Instr instr = opcode | (rs.code() << kRsShift) | SF | (j & kImm16Mask); 11471cb0ef41Sopenharmony_ci emit(instr, is_compact_branch); 11481cb0ef41Sopenharmony_ci} 11491cb0ef41Sopenharmony_ci 11501cb0ef41Sopenharmony_civoid Assembler::GenInstrImmediate(Opcode opcode, Register rs, FPURegister ft, 11511cb0ef41Sopenharmony_ci int32_t j, 11521cb0ef41Sopenharmony_ci CompactBranchType is_compact_branch) { 11531cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j))); 11541cb0ef41Sopenharmony_ci Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift) | 11551cb0ef41Sopenharmony_ci (j & kImm16Mask); 11561cb0ef41Sopenharmony_ci emit(instr, is_compact_branch); 11571cb0ef41Sopenharmony_ci} 11581cb0ef41Sopenharmony_ci 11591cb0ef41Sopenharmony_civoid Assembler::GenInstrImmediate(Opcode opcode, Register rs, int32_t offset21, 11601cb0ef41Sopenharmony_ci CompactBranchType is_compact_branch) { 11611cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && (is_int21(offset21))); 11621cb0ef41Sopenharmony_ci Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask); 11631cb0ef41Sopenharmony_ci emit(instr, is_compact_branch); 11641cb0ef41Sopenharmony_ci} 11651cb0ef41Sopenharmony_ci 11661cb0ef41Sopenharmony_civoid Assembler::GenInstrImmediate(Opcode opcode, Register rs, 11671cb0ef41Sopenharmony_ci uint32_t offset21) { 11681cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && (is_uint21(offset21))); 11691cb0ef41Sopenharmony_ci Instr instr = opcode | (rs.code() << kRsShift) | (offset21 & kImm21Mask); 11701cb0ef41Sopenharmony_ci emit(instr); 11711cb0ef41Sopenharmony_ci} 11721cb0ef41Sopenharmony_ci 11731cb0ef41Sopenharmony_civoid Assembler::GenInstrImmediate(Opcode opcode, int32_t offset26, 11741cb0ef41Sopenharmony_ci CompactBranchType is_compact_branch) { 11751cb0ef41Sopenharmony_ci DCHECK(is_int26(offset26)); 11761cb0ef41Sopenharmony_ci Instr instr = opcode | (offset26 & kImm26Mask); 11771cb0ef41Sopenharmony_ci emit(instr, is_compact_branch); 11781cb0ef41Sopenharmony_ci} 11791cb0ef41Sopenharmony_ci 11801cb0ef41Sopenharmony_civoid Assembler::GenInstrJump(Opcode opcode, uint32_t address) { 11811cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 11821cb0ef41Sopenharmony_ci DCHECK(is_uint26(address)); 11831cb0ef41Sopenharmony_ci Instr instr = opcode | address; 11841cb0ef41Sopenharmony_ci emit(instr); 11851cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 11861cb0ef41Sopenharmony_ci} 11871cb0ef41Sopenharmony_ci 11881cb0ef41Sopenharmony_ci// MSA instructions 11891cb0ef41Sopenharmony_civoid Assembler::GenInstrMsaI8(SecondaryField operation, uint32_t imm8, 11901cb0ef41Sopenharmony_ci MSARegister ws, MSARegister wd) { 11911cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 11921cb0ef41Sopenharmony_ci DCHECK(ws.is_valid() && wd.is_valid() && is_uint8(imm8)); 11931cb0ef41Sopenharmony_ci Instr instr = MSA | operation | ((imm8 & kImm8Mask) << kWtShift) | 11941cb0ef41Sopenharmony_ci (ws.code() << kWsShift) | (wd.code() << kWdShift); 11951cb0ef41Sopenharmony_ci emit(instr); 11961cb0ef41Sopenharmony_ci} 11971cb0ef41Sopenharmony_ci 11981cb0ef41Sopenharmony_civoid Assembler::GenInstrMsaI5(SecondaryField operation, SecondaryField df, 11991cb0ef41Sopenharmony_ci int32_t imm5, MSARegister ws, MSARegister wd) { 12001cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 12011cb0ef41Sopenharmony_ci DCHECK(ws.is_valid() && wd.is_valid()); 12021cb0ef41Sopenharmony_ci DCHECK((operation == MAXI_S) || (operation == MINI_S) || 12031cb0ef41Sopenharmony_ci (operation == CEQI) || (operation == CLTI_S) || 12041cb0ef41Sopenharmony_ci (operation == CLEI_S) 12051cb0ef41Sopenharmony_ci ? is_int5(imm5) 12061cb0ef41Sopenharmony_ci : is_uint5(imm5)); 12071cb0ef41Sopenharmony_ci Instr instr = MSA | operation | df | ((imm5 & kImm5Mask) << kWtShift) | 12081cb0ef41Sopenharmony_ci (ws.code() << kWsShift) | (wd.code() << kWdShift); 12091cb0ef41Sopenharmony_ci emit(instr); 12101cb0ef41Sopenharmony_ci} 12111cb0ef41Sopenharmony_ci 12121cb0ef41Sopenharmony_civoid Assembler::GenInstrMsaBit(SecondaryField operation, SecondaryField df, 12131cb0ef41Sopenharmony_ci uint32_t m, MSARegister ws, MSARegister wd) { 12141cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 12151cb0ef41Sopenharmony_ci DCHECK(ws.is_valid() && wd.is_valid() && is_valid_msa_df_m(df, m)); 12161cb0ef41Sopenharmony_ci Instr instr = MSA | operation | df | (m << kWtShift) | 12171cb0ef41Sopenharmony_ci (ws.code() << kWsShift) | (wd.code() << kWdShift); 12181cb0ef41Sopenharmony_ci emit(instr); 12191cb0ef41Sopenharmony_ci} 12201cb0ef41Sopenharmony_ci 12211cb0ef41Sopenharmony_civoid Assembler::GenInstrMsaI10(SecondaryField operation, SecondaryField df, 12221cb0ef41Sopenharmony_ci int32_t imm10, MSARegister wd) { 12231cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 12241cb0ef41Sopenharmony_ci DCHECK(wd.is_valid() && is_int10(imm10)); 12251cb0ef41Sopenharmony_ci Instr instr = MSA | operation | df | ((imm10 & kImm10Mask) << kWsShift) | 12261cb0ef41Sopenharmony_ci (wd.code() << kWdShift); 12271cb0ef41Sopenharmony_ci emit(instr); 12281cb0ef41Sopenharmony_ci} 12291cb0ef41Sopenharmony_ci 12301cb0ef41Sopenharmony_citemplate <typename RegType> 12311cb0ef41Sopenharmony_civoid Assembler::GenInstrMsa3R(SecondaryField operation, SecondaryField df, 12321cb0ef41Sopenharmony_ci RegType t, MSARegister ws, MSARegister wd) { 12331cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 12341cb0ef41Sopenharmony_ci DCHECK(t.is_valid() && ws.is_valid() && wd.is_valid()); 12351cb0ef41Sopenharmony_ci Instr instr = MSA | operation | df | (t.code() << kWtShift) | 12361cb0ef41Sopenharmony_ci (ws.code() << kWsShift) | (wd.code() << kWdShift); 12371cb0ef41Sopenharmony_ci emit(instr); 12381cb0ef41Sopenharmony_ci} 12391cb0ef41Sopenharmony_ci 12401cb0ef41Sopenharmony_citemplate <typename DstType, typename SrcType> 12411cb0ef41Sopenharmony_civoid Assembler::GenInstrMsaElm(SecondaryField operation, SecondaryField df, 12421cb0ef41Sopenharmony_ci uint32_t n, SrcType src, DstType dst) { 12431cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 12441cb0ef41Sopenharmony_ci DCHECK(src.is_valid() && dst.is_valid() && is_valid_msa_df_n(df, n)); 12451cb0ef41Sopenharmony_ci Instr instr = MSA | operation | df | (n << kWtShift) | 12461cb0ef41Sopenharmony_ci (src.code() << kWsShift) | (dst.code() << kWdShift) | 12471cb0ef41Sopenharmony_ci MSA_ELM_MINOR; 12481cb0ef41Sopenharmony_ci emit(instr); 12491cb0ef41Sopenharmony_ci} 12501cb0ef41Sopenharmony_ci 12511cb0ef41Sopenharmony_civoid Assembler::GenInstrMsa3RF(SecondaryField operation, uint32_t df, 12521cb0ef41Sopenharmony_ci MSARegister wt, MSARegister ws, MSARegister wd) { 12531cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 12541cb0ef41Sopenharmony_ci DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid()); 12551cb0ef41Sopenharmony_ci DCHECK_LT(df, 2); 12561cb0ef41Sopenharmony_ci Instr instr = MSA | operation | (df << 21) | (wt.code() << kWtShift) | 12571cb0ef41Sopenharmony_ci (ws.code() << kWsShift) | (wd.code() << kWdShift); 12581cb0ef41Sopenharmony_ci emit(instr); 12591cb0ef41Sopenharmony_ci} 12601cb0ef41Sopenharmony_ci 12611cb0ef41Sopenharmony_civoid Assembler::GenInstrMsaVec(SecondaryField operation, MSARegister wt, 12621cb0ef41Sopenharmony_ci MSARegister ws, MSARegister wd) { 12631cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 12641cb0ef41Sopenharmony_ci DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid()); 12651cb0ef41Sopenharmony_ci Instr instr = MSA | operation | (wt.code() << kWtShift) | 12661cb0ef41Sopenharmony_ci (ws.code() << kWsShift) | (wd.code() << kWdShift) | 12671cb0ef41Sopenharmony_ci MSA_VEC_2R_2RF_MINOR; 12681cb0ef41Sopenharmony_ci emit(instr); 12691cb0ef41Sopenharmony_ci} 12701cb0ef41Sopenharmony_ci 12711cb0ef41Sopenharmony_civoid Assembler::GenInstrMsaMI10(SecondaryField operation, int32_t s10, 12721cb0ef41Sopenharmony_ci Register rs, MSARegister wd) { 12731cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 12741cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && wd.is_valid() && is_int10(s10)); 12751cb0ef41Sopenharmony_ci Instr instr = MSA | operation | ((s10 & kImm10Mask) << kWtShift) | 12761cb0ef41Sopenharmony_ci (rs.code() << kWsShift) | (wd.code() << kWdShift); 12771cb0ef41Sopenharmony_ci emit(instr); 12781cb0ef41Sopenharmony_ci} 12791cb0ef41Sopenharmony_ci 12801cb0ef41Sopenharmony_civoid Assembler::GenInstrMsa2R(SecondaryField operation, SecondaryField df, 12811cb0ef41Sopenharmony_ci MSARegister ws, MSARegister wd) { 12821cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 12831cb0ef41Sopenharmony_ci DCHECK(ws.is_valid() && wd.is_valid()); 12841cb0ef41Sopenharmony_ci Instr instr = MSA | MSA_2R_FORMAT | operation | df | (ws.code() << kWsShift) | 12851cb0ef41Sopenharmony_ci (wd.code() << kWdShift) | MSA_VEC_2R_2RF_MINOR; 12861cb0ef41Sopenharmony_ci emit(instr); 12871cb0ef41Sopenharmony_ci} 12881cb0ef41Sopenharmony_ci 12891cb0ef41Sopenharmony_civoid Assembler::GenInstrMsa2RF(SecondaryField operation, SecondaryField df, 12901cb0ef41Sopenharmony_ci MSARegister ws, MSARegister wd) { 12911cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 12921cb0ef41Sopenharmony_ci DCHECK(ws.is_valid() && wd.is_valid()); 12931cb0ef41Sopenharmony_ci Instr instr = MSA | MSA_2RF_FORMAT | operation | df | 12941cb0ef41Sopenharmony_ci (ws.code() << kWsShift) | (wd.code() << kWdShift) | 12951cb0ef41Sopenharmony_ci MSA_VEC_2R_2RF_MINOR; 12961cb0ef41Sopenharmony_ci emit(instr); 12971cb0ef41Sopenharmony_ci} 12981cb0ef41Sopenharmony_ci 12991cb0ef41Sopenharmony_civoid Assembler::GenInstrMsaBranch(SecondaryField operation, MSARegister wt, 13001cb0ef41Sopenharmony_ci int32_t offset16) { 13011cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 13021cb0ef41Sopenharmony_ci DCHECK(wt.is_valid() && is_int16(offset16)); 13031cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 13041cb0ef41Sopenharmony_ci Instr instr = 13051cb0ef41Sopenharmony_ci COP1 | operation | (wt.code() << kWtShift) | (offset16 & kImm16Mask); 13061cb0ef41Sopenharmony_ci emit(instr); 13071cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 13081cb0ef41Sopenharmony_ci} 13091cb0ef41Sopenharmony_ci 13101cb0ef41Sopenharmony_ci// Returns the next free trampoline entry. 13111cb0ef41Sopenharmony_ciint32_t Assembler::get_trampoline_entry(int32_t pos) { 13121cb0ef41Sopenharmony_ci int32_t trampoline_entry = kInvalidSlotPos; 13131cb0ef41Sopenharmony_ci if (!internal_trampoline_exception_) { 13141cb0ef41Sopenharmony_ci if (trampoline_.start() > pos) { 13151cb0ef41Sopenharmony_ci trampoline_entry = trampoline_.take_slot(); 13161cb0ef41Sopenharmony_ci } 13171cb0ef41Sopenharmony_ci 13181cb0ef41Sopenharmony_ci if (kInvalidSlotPos == trampoline_entry) { 13191cb0ef41Sopenharmony_ci internal_trampoline_exception_ = true; 13201cb0ef41Sopenharmony_ci } 13211cb0ef41Sopenharmony_ci } 13221cb0ef41Sopenharmony_ci return trampoline_entry; 13231cb0ef41Sopenharmony_ci} 13241cb0ef41Sopenharmony_ci 13251cb0ef41Sopenharmony_ciuint64_t Assembler::jump_address(Label* L) { 13261cb0ef41Sopenharmony_ci int64_t target_pos; 13271cb0ef41Sopenharmony_ci if (L->is_bound()) { 13281cb0ef41Sopenharmony_ci target_pos = L->pos(); 13291cb0ef41Sopenharmony_ci } else { 13301cb0ef41Sopenharmony_ci if (L->is_linked()) { 13311cb0ef41Sopenharmony_ci target_pos = L->pos(); // L's link. 13321cb0ef41Sopenharmony_ci L->link_to(pc_offset()); 13331cb0ef41Sopenharmony_ci } else { 13341cb0ef41Sopenharmony_ci L->link_to(pc_offset()); 13351cb0ef41Sopenharmony_ci return kEndOfJumpChain; 13361cb0ef41Sopenharmony_ci } 13371cb0ef41Sopenharmony_ci } 13381cb0ef41Sopenharmony_ci uint64_t imm = reinterpret_cast<uint64_t>(buffer_start_) + target_pos; 13391cb0ef41Sopenharmony_ci DCHECK_EQ(imm & 3, 0); 13401cb0ef41Sopenharmony_ci 13411cb0ef41Sopenharmony_ci return imm; 13421cb0ef41Sopenharmony_ci} 13431cb0ef41Sopenharmony_ci 13441cb0ef41Sopenharmony_ciuint64_t Assembler::jump_offset(Label* L) { 13451cb0ef41Sopenharmony_ci int64_t target_pos; 13461cb0ef41Sopenharmony_ci int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0; 13471cb0ef41Sopenharmony_ci 13481cb0ef41Sopenharmony_ci if (L->is_bound()) { 13491cb0ef41Sopenharmony_ci target_pos = L->pos(); 13501cb0ef41Sopenharmony_ci } else { 13511cb0ef41Sopenharmony_ci if (L->is_linked()) { 13521cb0ef41Sopenharmony_ci target_pos = L->pos(); // L's link. 13531cb0ef41Sopenharmony_ci L->link_to(pc_offset() + pad); 13541cb0ef41Sopenharmony_ci } else { 13551cb0ef41Sopenharmony_ci L->link_to(pc_offset() + pad); 13561cb0ef41Sopenharmony_ci return kEndOfJumpChain; 13571cb0ef41Sopenharmony_ci } 13581cb0ef41Sopenharmony_ci } 13591cb0ef41Sopenharmony_ci int64_t imm = target_pos - (pc_offset() + pad); 13601cb0ef41Sopenharmony_ci DCHECK_EQ(imm & 3, 0); 13611cb0ef41Sopenharmony_ci 13621cb0ef41Sopenharmony_ci return static_cast<uint64_t>(imm); 13631cb0ef41Sopenharmony_ci} 13641cb0ef41Sopenharmony_ci 13651cb0ef41Sopenharmony_ciuint64_t Assembler::branch_long_offset(Label* L) { 13661cb0ef41Sopenharmony_ci int64_t target_pos; 13671cb0ef41Sopenharmony_ci 13681cb0ef41Sopenharmony_ci if (L->is_bound()) { 13691cb0ef41Sopenharmony_ci target_pos = L->pos(); 13701cb0ef41Sopenharmony_ci } else { 13711cb0ef41Sopenharmony_ci if (L->is_linked()) { 13721cb0ef41Sopenharmony_ci target_pos = L->pos(); // L's link. 13731cb0ef41Sopenharmony_ci L->link_to(pc_offset()); 13741cb0ef41Sopenharmony_ci } else { 13751cb0ef41Sopenharmony_ci L->link_to(pc_offset()); 13761cb0ef41Sopenharmony_ci return kEndOfJumpChain; 13771cb0ef41Sopenharmony_ci } 13781cb0ef41Sopenharmony_ci } 13791cb0ef41Sopenharmony_ci int64_t offset = target_pos - (pc_offset() + kLongBranchPCOffset); 13801cb0ef41Sopenharmony_ci DCHECK_EQ(offset & 3, 0); 13811cb0ef41Sopenharmony_ci 13821cb0ef41Sopenharmony_ci return static_cast<uint64_t>(offset); 13831cb0ef41Sopenharmony_ci} 13841cb0ef41Sopenharmony_ci 13851cb0ef41Sopenharmony_ciint32_t Assembler::branch_offset_helper(Label* L, OffsetSize bits) { 13861cb0ef41Sopenharmony_ci int32_t target_pos; 13871cb0ef41Sopenharmony_ci int32_t pad = IsPrevInstrCompactBranch() ? kInstrSize : 0; 13881cb0ef41Sopenharmony_ci 13891cb0ef41Sopenharmony_ci if (L->is_bound()) { 13901cb0ef41Sopenharmony_ci target_pos = L->pos(); 13911cb0ef41Sopenharmony_ci } else { 13921cb0ef41Sopenharmony_ci if (L->is_linked()) { 13931cb0ef41Sopenharmony_ci target_pos = L->pos(); 13941cb0ef41Sopenharmony_ci L->link_to(pc_offset() + pad); 13951cb0ef41Sopenharmony_ci } else { 13961cb0ef41Sopenharmony_ci L->link_to(pc_offset() + pad); 13971cb0ef41Sopenharmony_ci if (!trampoline_emitted_) { 13981cb0ef41Sopenharmony_ci unbound_labels_count_++; 13991cb0ef41Sopenharmony_ci next_buffer_check_ -= kTrampolineSlotsSize; 14001cb0ef41Sopenharmony_ci } 14011cb0ef41Sopenharmony_ci return kEndOfChain; 14021cb0ef41Sopenharmony_ci } 14031cb0ef41Sopenharmony_ci } 14041cb0ef41Sopenharmony_ci 14051cb0ef41Sopenharmony_ci int32_t offset = target_pos - (pc_offset() + kBranchPCOffset + pad); 14061cb0ef41Sopenharmony_ci DCHECK(is_intn(offset, bits + 2)); 14071cb0ef41Sopenharmony_ci DCHECK_EQ(offset & 3, 0); 14081cb0ef41Sopenharmony_ci 14091cb0ef41Sopenharmony_ci return offset; 14101cb0ef41Sopenharmony_ci} 14111cb0ef41Sopenharmony_ci 14121cb0ef41Sopenharmony_civoid Assembler::label_at_put(Label* L, int at_offset) { 14131cb0ef41Sopenharmony_ci int target_pos; 14141cb0ef41Sopenharmony_ci if (L->is_bound()) { 14151cb0ef41Sopenharmony_ci target_pos = L->pos(); 14161cb0ef41Sopenharmony_ci instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); 14171cb0ef41Sopenharmony_ci } else { 14181cb0ef41Sopenharmony_ci if (L->is_linked()) { 14191cb0ef41Sopenharmony_ci target_pos = L->pos(); // L's link. 14201cb0ef41Sopenharmony_ci int32_t imm18 = target_pos - at_offset; 14211cb0ef41Sopenharmony_ci DCHECK_EQ(imm18 & 3, 0); 14221cb0ef41Sopenharmony_ci int32_t imm16 = imm18 >> 2; 14231cb0ef41Sopenharmony_ci DCHECK(is_int16(imm16)); 14241cb0ef41Sopenharmony_ci instr_at_put(at_offset, (imm16 & kImm16Mask)); 14251cb0ef41Sopenharmony_ci } else { 14261cb0ef41Sopenharmony_ci target_pos = kEndOfChain; 14271cb0ef41Sopenharmony_ci instr_at_put(at_offset, 0); 14281cb0ef41Sopenharmony_ci if (!trampoline_emitted_) { 14291cb0ef41Sopenharmony_ci unbound_labels_count_++; 14301cb0ef41Sopenharmony_ci next_buffer_check_ -= kTrampolineSlotsSize; 14311cb0ef41Sopenharmony_ci } 14321cb0ef41Sopenharmony_ci } 14331cb0ef41Sopenharmony_ci L->link_to(at_offset); 14341cb0ef41Sopenharmony_ci } 14351cb0ef41Sopenharmony_ci} 14361cb0ef41Sopenharmony_ci 14371cb0ef41Sopenharmony_ci//------- Branch and jump instructions -------- 14381cb0ef41Sopenharmony_ci 14391cb0ef41Sopenharmony_civoid Assembler::b(int16_t offset) { beq(zero_reg, zero_reg, offset); } 14401cb0ef41Sopenharmony_ci 14411cb0ef41Sopenharmony_civoid Assembler::bal(int16_t offset) { bgezal(zero_reg, offset); } 14421cb0ef41Sopenharmony_ci 14431cb0ef41Sopenharmony_civoid Assembler::bc(int32_t offset) { 14441cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 14451cb0ef41Sopenharmony_ci GenInstrImmediate(BC, offset, CompactBranchType::COMPACT_BRANCH); 14461cb0ef41Sopenharmony_ci} 14471cb0ef41Sopenharmony_ci 14481cb0ef41Sopenharmony_civoid Assembler::balc(int32_t offset) { 14491cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 14501cb0ef41Sopenharmony_ci GenInstrImmediate(BALC, offset, CompactBranchType::COMPACT_BRANCH); 14511cb0ef41Sopenharmony_ci} 14521cb0ef41Sopenharmony_ci 14531cb0ef41Sopenharmony_civoid Assembler::beq(Register rs, Register rt, int16_t offset) { 14541cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 14551cb0ef41Sopenharmony_ci GenInstrImmediate(BEQ, rs, rt, offset); 14561cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 14571cb0ef41Sopenharmony_ci} 14581cb0ef41Sopenharmony_ci 14591cb0ef41Sopenharmony_civoid Assembler::bgez(Register rs, int16_t offset) { 14601cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 14611cb0ef41Sopenharmony_ci GenInstrImmediate(REGIMM, rs, BGEZ, offset); 14621cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 14631cb0ef41Sopenharmony_ci} 14641cb0ef41Sopenharmony_ci 14651cb0ef41Sopenharmony_civoid Assembler::bgezc(Register rt, int16_t offset) { 14661cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 14671cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 14681cb0ef41Sopenharmony_ci GenInstrImmediate(BLEZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); 14691cb0ef41Sopenharmony_ci} 14701cb0ef41Sopenharmony_ci 14711cb0ef41Sopenharmony_civoid Assembler::bgeuc(Register rs, Register rt, int16_t offset) { 14721cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 14731cb0ef41Sopenharmony_ci DCHECK(rs != zero_reg); 14741cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 14751cb0ef41Sopenharmony_ci DCHECK(rs.code() != rt.code()); 14761cb0ef41Sopenharmony_ci GenInstrImmediate(BLEZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 14771cb0ef41Sopenharmony_ci} 14781cb0ef41Sopenharmony_ci 14791cb0ef41Sopenharmony_civoid Assembler::bgec(Register rs, Register rt, int16_t offset) { 14801cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 14811cb0ef41Sopenharmony_ci DCHECK(rs != zero_reg); 14821cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 14831cb0ef41Sopenharmony_ci DCHECK(rs.code() != rt.code()); 14841cb0ef41Sopenharmony_ci GenInstrImmediate(BLEZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 14851cb0ef41Sopenharmony_ci} 14861cb0ef41Sopenharmony_ci 14871cb0ef41Sopenharmony_civoid Assembler::bgezal(Register rs, int16_t offset) { 14881cb0ef41Sopenharmony_ci DCHECK(kArchVariant != kMips64r6 || rs == zero_reg); 14891cb0ef41Sopenharmony_ci DCHECK(rs != ra); 14901cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 14911cb0ef41Sopenharmony_ci GenInstrImmediate(REGIMM, rs, BGEZAL, offset); 14921cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 14931cb0ef41Sopenharmony_ci} 14941cb0ef41Sopenharmony_ci 14951cb0ef41Sopenharmony_civoid Assembler::bgtz(Register rs, int16_t offset) { 14961cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 14971cb0ef41Sopenharmony_ci GenInstrImmediate(BGTZ, rs, zero_reg, offset); 14981cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 14991cb0ef41Sopenharmony_ci} 15001cb0ef41Sopenharmony_ci 15011cb0ef41Sopenharmony_civoid Assembler::bgtzc(Register rt, int16_t offset) { 15021cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 15031cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 15041cb0ef41Sopenharmony_ci GenInstrImmediate(BGTZL, zero_reg, rt, offset, 15051cb0ef41Sopenharmony_ci CompactBranchType::COMPACT_BRANCH); 15061cb0ef41Sopenharmony_ci} 15071cb0ef41Sopenharmony_ci 15081cb0ef41Sopenharmony_civoid Assembler::blez(Register rs, int16_t offset) { 15091cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 15101cb0ef41Sopenharmony_ci GenInstrImmediate(BLEZ, rs, zero_reg, offset); 15111cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 15121cb0ef41Sopenharmony_ci} 15131cb0ef41Sopenharmony_ci 15141cb0ef41Sopenharmony_civoid Assembler::blezc(Register rt, int16_t offset) { 15151cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 15161cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 15171cb0ef41Sopenharmony_ci GenInstrImmediate(BLEZL, zero_reg, rt, offset, 15181cb0ef41Sopenharmony_ci CompactBranchType::COMPACT_BRANCH); 15191cb0ef41Sopenharmony_ci} 15201cb0ef41Sopenharmony_ci 15211cb0ef41Sopenharmony_civoid Assembler::bltzc(Register rt, int16_t offset) { 15221cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 15231cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 15241cb0ef41Sopenharmony_ci GenInstrImmediate(BGTZL, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); 15251cb0ef41Sopenharmony_ci} 15261cb0ef41Sopenharmony_ci 15271cb0ef41Sopenharmony_civoid Assembler::bltuc(Register rs, Register rt, int16_t offset) { 15281cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 15291cb0ef41Sopenharmony_ci DCHECK(rs != zero_reg); 15301cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 15311cb0ef41Sopenharmony_ci DCHECK(rs.code() != rt.code()); 15321cb0ef41Sopenharmony_ci GenInstrImmediate(BGTZ, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 15331cb0ef41Sopenharmony_ci} 15341cb0ef41Sopenharmony_ci 15351cb0ef41Sopenharmony_civoid Assembler::bltc(Register rs, Register rt, int16_t offset) { 15361cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 15371cb0ef41Sopenharmony_ci DCHECK(rs != zero_reg); 15381cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 15391cb0ef41Sopenharmony_ci DCHECK(rs.code() != rt.code()); 15401cb0ef41Sopenharmony_ci GenInstrImmediate(BGTZL, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 15411cb0ef41Sopenharmony_ci} 15421cb0ef41Sopenharmony_ci 15431cb0ef41Sopenharmony_civoid Assembler::bltz(Register rs, int16_t offset) { 15441cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 15451cb0ef41Sopenharmony_ci GenInstrImmediate(REGIMM, rs, BLTZ, offset); 15461cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 15471cb0ef41Sopenharmony_ci} 15481cb0ef41Sopenharmony_ci 15491cb0ef41Sopenharmony_civoid Assembler::bltzal(Register rs, int16_t offset) { 15501cb0ef41Sopenharmony_ci DCHECK(kArchVariant != kMips64r6 || rs == zero_reg); 15511cb0ef41Sopenharmony_ci DCHECK(rs != ra); 15521cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 15531cb0ef41Sopenharmony_ci GenInstrImmediate(REGIMM, rs, BLTZAL, offset); 15541cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 15551cb0ef41Sopenharmony_ci} 15561cb0ef41Sopenharmony_ci 15571cb0ef41Sopenharmony_civoid Assembler::bne(Register rs, Register rt, int16_t offset) { 15581cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 15591cb0ef41Sopenharmony_ci GenInstrImmediate(BNE, rs, rt, offset); 15601cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 15611cb0ef41Sopenharmony_ci} 15621cb0ef41Sopenharmony_ci 15631cb0ef41Sopenharmony_civoid Assembler::bovc(Register rs, Register rt, int16_t offset) { 15641cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 15651cb0ef41Sopenharmony_ci if (rs.code() >= rt.code()) { 15661cb0ef41Sopenharmony_ci GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 15671cb0ef41Sopenharmony_ci } else { 15681cb0ef41Sopenharmony_ci GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH); 15691cb0ef41Sopenharmony_ci } 15701cb0ef41Sopenharmony_ci} 15711cb0ef41Sopenharmony_ci 15721cb0ef41Sopenharmony_civoid Assembler::bnvc(Register rs, Register rt, int16_t offset) { 15731cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 15741cb0ef41Sopenharmony_ci if (rs.code() >= rt.code()) { 15751cb0ef41Sopenharmony_ci GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 15761cb0ef41Sopenharmony_ci } else { 15771cb0ef41Sopenharmony_ci GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH); 15781cb0ef41Sopenharmony_ci } 15791cb0ef41Sopenharmony_ci} 15801cb0ef41Sopenharmony_ci 15811cb0ef41Sopenharmony_civoid Assembler::blezalc(Register rt, int16_t offset) { 15821cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 15831cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 15841cb0ef41Sopenharmony_ci DCHECK(rt != ra); 15851cb0ef41Sopenharmony_ci GenInstrImmediate(BLEZ, zero_reg, rt, offset, 15861cb0ef41Sopenharmony_ci CompactBranchType::COMPACT_BRANCH); 15871cb0ef41Sopenharmony_ci} 15881cb0ef41Sopenharmony_ci 15891cb0ef41Sopenharmony_civoid Assembler::bgezalc(Register rt, int16_t offset) { 15901cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 15911cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 15921cb0ef41Sopenharmony_ci DCHECK(rt != ra); 15931cb0ef41Sopenharmony_ci GenInstrImmediate(BLEZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); 15941cb0ef41Sopenharmony_ci} 15951cb0ef41Sopenharmony_ci 15961cb0ef41Sopenharmony_civoid Assembler::bgezall(Register rs, int16_t offset) { 15971cb0ef41Sopenharmony_ci DCHECK_NE(kArchVariant, kMips64r6); 15981cb0ef41Sopenharmony_ci DCHECK(rs != zero_reg); 15991cb0ef41Sopenharmony_ci DCHECK(rs != ra); 16001cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 16011cb0ef41Sopenharmony_ci GenInstrImmediate(REGIMM, rs, BGEZALL, offset); 16021cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 16031cb0ef41Sopenharmony_ci} 16041cb0ef41Sopenharmony_ci 16051cb0ef41Sopenharmony_civoid Assembler::bltzalc(Register rt, int16_t offset) { 16061cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 16071cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 16081cb0ef41Sopenharmony_ci DCHECK(rt != ra); 16091cb0ef41Sopenharmony_ci GenInstrImmediate(BGTZ, rt, rt, offset, CompactBranchType::COMPACT_BRANCH); 16101cb0ef41Sopenharmony_ci} 16111cb0ef41Sopenharmony_ci 16121cb0ef41Sopenharmony_civoid Assembler::bgtzalc(Register rt, int16_t offset) { 16131cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 16141cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 16151cb0ef41Sopenharmony_ci DCHECK(rt != ra); 16161cb0ef41Sopenharmony_ci GenInstrImmediate(BGTZ, zero_reg, rt, offset, 16171cb0ef41Sopenharmony_ci CompactBranchType::COMPACT_BRANCH); 16181cb0ef41Sopenharmony_ci} 16191cb0ef41Sopenharmony_ci 16201cb0ef41Sopenharmony_civoid Assembler::beqzalc(Register rt, int16_t offset) { 16211cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 16221cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 16231cb0ef41Sopenharmony_ci DCHECK(rt != ra); 16241cb0ef41Sopenharmony_ci GenInstrImmediate(ADDI, zero_reg, rt, offset, 16251cb0ef41Sopenharmony_ci CompactBranchType::COMPACT_BRANCH); 16261cb0ef41Sopenharmony_ci} 16271cb0ef41Sopenharmony_ci 16281cb0ef41Sopenharmony_civoid Assembler::bnezalc(Register rt, int16_t offset) { 16291cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 16301cb0ef41Sopenharmony_ci DCHECK(rt != zero_reg); 16311cb0ef41Sopenharmony_ci DCHECK(rt != ra); 16321cb0ef41Sopenharmony_ci GenInstrImmediate(DADDI, zero_reg, rt, offset, 16331cb0ef41Sopenharmony_ci CompactBranchType::COMPACT_BRANCH); 16341cb0ef41Sopenharmony_ci} 16351cb0ef41Sopenharmony_ci 16361cb0ef41Sopenharmony_civoid Assembler::beqc(Register rs, Register rt, int16_t offset) { 16371cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 16381cb0ef41Sopenharmony_ci DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0); 16391cb0ef41Sopenharmony_ci if (rs.code() < rt.code()) { 16401cb0ef41Sopenharmony_ci GenInstrImmediate(ADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 16411cb0ef41Sopenharmony_ci } else { 16421cb0ef41Sopenharmony_ci GenInstrImmediate(ADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH); 16431cb0ef41Sopenharmony_ci } 16441cb0ef41Sopenharmony_ci} 16451cb0ef41Sopenharmony_ci 16461cb0ef41Sopenharmony_civoid Assembler::beqzc(Register rs, int32_t offset) { 16471cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 16481cb0ef41Sopenharmony_ci DCHECK(rs != zero_reg); 16491cb0ef41Sopenharmony_ci GenInstrImmediate(POP66, rs, offset, CompactBranchType::COMPACT_BRANCH); 16501cb0ef41Sopenharmony_ci} 16511cb0ef41Sopenharmony_ci 16521cb0ef41Sopenharmony_civoid Assembler::bnec(Register rs, Register rt, int16_t offset) { 16531cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 16541cb0ef41Sopenharmony_ci DCHECK(rs.code() != rt.code() && rs.code() != 0 && rt.code() != 0); 16551cb0ef41Sopenharmony_ci if (rs.code() < rt.code()) { 16561cb0ef41Sopenharmony_ci GenInstrImmediate(DADDI, rs, rt, offset, CompactBranchType::COMPACT_BRANCH); 16571cb0ef41Sopenharmony_ci } else { 16581cb0ef41Sopenharmony_ci GenInstrImmediate(DADDI, rt, rs, offset, CompactBranchType::COMPACT_BRANCH); 16591cb0ef41Sopenharmony_ci } 16601cb0ef41Sopenharmony_ci} 16611cb0ef41Sopenharmony_ci 16621cb0ef41Sopenharmony_civoid Assembler::bnezc(Register rs, int32_t offset) { 16631cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 16641cb0ef41Sopenharmony_ci DCHECK(rs != zero_reg); 16651cb0ef41Sopenharmony_ci GenInstrImmediate(POP76, rs, offset, CompactBranchType::COMPACT_BRANCH); 16661cb0ef41Sopenharmony_ci} 16671cb0ef41Sopenharmony_ci 16681cb0ef41Sopenharmony_civoid Assembler::j(int64_t target) { 16691cb0ef41Sopenharmony_ci // Deprecated. Use PC-relative jumps instead. 16701cb0ef41Sopenharmony_ci UNREACHABLE(); 16711cb0ef41Sopenharmony_ci} 16721cb0ef41Sopenharmony_ci 16731cb0ef41Sopenharmony_civoid Assembler::j(Label* target) { 16741cb0ef41Sopenharmony_ci // Deprecated. Use PC-relative jumps instead. 16751cb0ef41Sopenharmony_ci UNREACHABLE(); 16761cb0ef41Sopenharmony_ci} 16771cb0ef41Sopenharmony_ci 16781cb0ef41Sopenharmony_civoid Assembler::jal(Label* target) { 16791cb0ef41Sopenharmony_ci // Deprecated. Use PC-relative jumps instead. 16801cb0ef41Sopenharmony_ci UNREACHABLE(); 16811cb0ef41Sopenharmony_ci} 16821cb0ef41Sopenharmony_ci 16831cb0ef41Sopenharmony_civoid Assembler::jal(int64_t target) { 16841cb0ef41Sopenharmony_ci // Deprecated. Use PC-relative jumps instead. 16851cb0ef41Sopenharmony_ci UNREACHABLE(); 16861cb0ef41Sopenharmony_ci} 16871cb0ef41Sopenharmony_ci 16881cb0ef41Sopenharmony_civoid Assembler::jr(Register rs) { 16891cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 16901cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 16911cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR); 16921cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 16931cb0ef41Sopenharmony_ci } else { 16941cb0ef41Sopenharmony_ci jalr(rs, zero_reg); 16951cb0ef41Sopenharmony_ci } 16961cb0ef41Sopenharmony_ci} 16971cb0ef41Sopenharmony_ci 16981cb0ef41Sopenharmony_civoid Assembler::jalr(Register rs, Register rd) { 16991cb0ef41Sopenharmony_ci DCHECK(rs.code() != rd.code()); 17001cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 17011cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, zero_reg, rd, 0, JALR); 17021cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 17031cb0ef41Sopenharmony_ci} 17041cb0ef41Sopenharmony_ci 17051cb0ef41Sopenharmony_civoid Assembler::jic(Register rt, int16_t offset) { 17061cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 17071cb0ef41Sopenharmony_ci GenInstrImmediate(POP66, zero_reg, rt, offset); 17081cb0ef41Sopenharmony_ci} 17091cb0ef41Sopenharmony_ci 17101cb0ef41Sopenharmony_civoid Assembler::jialc(Register rt, int16_t offset) { 17111cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 17121cb0ef41Sopenharmony_ci GenInstrImmediate(POP76, zero_reg, rt, offset); 17131cb0ef41Sopenharmony_ci} 17141cb0ef41Sopenharmony_ci 17151cb0ef41Sopenharmony_ci// -------Data-processing-instructions--------- 17161cb0ef41Sopenharmony_ci 17171cb0ef41Sopenharmony_ci// Arithmetic. 17181cb0ef41Sopenharmony_ci 17191cb0ef41Sopenharmony_civoid Assembler::addu(Register rd, Register rs, Register rt) { 17201cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU); 17211cb0ef41Sopenharmony_ci} 17221cb0ef41Sopenharmony_ci 17231cb0ef41Sopenharmony_civoid Assembler::addiu(Register rd, Register rs, int32_t j) { 17241cb0ef41Sopenharmony_ci GenInstrImmediate(ADDIU, rs, rd, j); 17251cb0ef41Sopenharmony_ci} 17261cb0ef41Sopenharmony_ci 17271cb0ef41Sopenharmony_civoid Assembler::subu(Register rd, Register rs, Register rt) { 17281cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU); 17291cb0ef41Sopenharmony_ci} 17301cb0ef41Sopenharmony_ci 17311cb0ef41Sopenharmony_civoid Assembler::mul(Register rd, Register rs, Register rt) { 17321cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 17331cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH); 17341cb0ef41Sopenharmony_ci } else { 17351cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL); 17361cb0ef41Sopenharmony_ci } 17371cb0ef41Sopenharmony_ci} 17381cb0ef41Sopenharmony_ci 17391cb0ef41Sopenharmony_civoid Assembler::muh(Register rd, Register rs, Register rt) { 17401cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 17411cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH); 17421cb0ef41Sopenharmony_ci} 17431cb0ef41Sopenharmony_ci 17441cb0ef41Sopenharmony_civoid Assembler::mulu(Register rd, Register rs, Register rt) { 17451cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 17461cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH_U); 17471cb0ef41Sopenharmony_ci} 17481cb0ef41Sopenharmony_ci 17491cb0ef41Sopenharmony_civoid Assembler::muhu(Register rd, Register rs, Register rt) { 17501cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 17511cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH_U); 17521cb0ef41Sopenharmony_ci} 17531cb0ef41Sopenharmony_ci 17541cb0ef41Sopenharmony_civoid Assembler::dmul(Register rd, Register rs, Register rt) { 17551cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 17561cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, D_MUL_MUH); 17571cb0ef41Sopenharmony_ci} 17581cb0ef41Sopenharmony_ci 17591cb0ef41Sopenharmony_civoid Assembler::dmuh(Register rd, Register rs, Register rt) { 17601cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 17611cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, D_MUL_MUH); 17621cb0ef41Sopenharmony_ci} 17631cb0ef41Sopenharmony_ci 17641cb0ef41Sopenharmony_civoid Assembler::dmulu(Register rd, Register rs, Register rt) { 17651cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 17661cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, D_MUL_MUH_U); 17671cb0ef41Sopenharmony_ci} 17681cb0ef41Sopenharmony_ci 17691cb0ef41Sopenharmony_civoid Assembler::dmuhu(Register rd, Register rs, Register rt) { 17701cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 17711cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, D_MUL_MUH_U); 17721cb0ef41Sopenharmony_ci} 17731cb0ef41Sopenharmony_ci 17741cb0ef41Sopenharmony_civoid Assembler::mult(Register rs, Register rt) { 17751cb0ef41Sopenharmony_ci DCHECK_NE(kArchVariant, kMips64r6); 17761cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT); 17771cb0ef41Sopenharmony_ci} 17781cb0ef41Sopenharmony_ci 17791cb0ef41Sopenharmony_civoid Assembler::multu(Register rs, Register rt) { 17801cb0ef41Sopenharmony_ci DCHECK_NE(kArchVariant, kMips64r6); 17811cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU); 17821cb0ef41Sopenharmony_ci} 17831cb0ef41Sopenharmony_ci 17841cb0ef41Sopenharmony_civoid Assembler::daddiu(Register rd, Register rs, int32_t j) { 17851cb0ef41Sopenharmony_ci GenInstrImmediate(DADDIU, rs, rd, j); 17861cb0ef41Sopenharmony_ci} 17871cb0ef41Sopenharmony_ci 17881cb0ef41Sopenharmony_civoid Assembler::div(Register rs, Register rt) { 17891cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV); 17901cb0ef41Sopenharmony_ci} 17911cb0ef41Sopenharmony_ci 17921cb0ef41Sopenharmony_civoid Assembler::div(Register rd, Register rs, Register rt) { 17931cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 17941cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD); 17951cb0ef41Sopenharmony_ci} 17961cb0ef41Sopenharmony_ci 17971cb0ef41Sopenharmony_civoid Assembler::mod(Register rd, Register rs, Register rt) { 17981cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 17991cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD); 18001cb0ef41Sopenharmony_ci} 18011cb0ef41Sopenharmony_ci 18021cb0ef41Sopenharmony_civoid Assembler::divu(Register rs, Register rt) { 18031cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU); 18041cb0ef41Sopenharmony_ci} 18051cb0ef41Sopenharmony_ci 18061cb0ef41Sopenharmony_civoid Assembler::divu(Register rd, Register rs, Register rt) { 18071cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 18081cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD_U); 18091cb0ef41Sopenharmony_ci} 18101cb0ef41Sopenharmony_ci 18111cb0ef41Sopenharmony_civoid Assembler::modu(Register rd, Register rs, Register rt) { 18121cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 18131cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD_U); 18141cb0ef41Sopenharmony_ci} 18151cb0ef41Sopenharmony_ci 18161cb0ef41Sopenharmony_civoid Assembler::daddu(Register rd, Register rs, Register rt) { 18171cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, DADDU); 18181cb0ef41Sopenharmony_ci} 18191cb0ef41Sopenharmony_ci 18201cb0ef41Sopenharmony_civoid Assembler::dsubu(Register rd, Register rs, Register rt) { 18211cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSUBU); 18221cb0ef41Sopenharmony_ci} 18231cb0ef41Sopenharmony_ci 18241cb0ef41Sopenharmony_civoid Assembler::dmult(Register rs, Register rt) { 18251cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULT); 18261cb0ef41Sopenharmony_ci} 18271cb0ef41Sopenharmony_ci 18281cb0ef41Sopenharmony_civoid Assembler::dmultu(Register rs, Register rt) { 18291cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DMULTU); 18301cb0ef41Sopenharmony_ci} 18311cb0ef41Sopenharmony_ci 18321cb0ef41Sopenharmony_civoid Assembler::ddiv(Register rs, Register rt) { 18331cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIV); 18341cb0ef41Sopenharmony_ci} 18351cb0ef41Sopenharmony_ci 18361cb0ef41Sopenharmony_civoid Assembler::ddiv(Register rd, Register rs, Register rt) { 18371cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 18381cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, D_DIV_MOD); 18391cb0ef41Sopenharmony_ci} 18401cb0ef41Sopenharmony_ci 18411cb0ef41Sopenharmony_civoid Assembler::dmod(Register rd, Register rs, Register rt) { 18421cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 18431cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, D_DIV_MOD); 18441cb0ef41Sopenharmony_ci} 18451cb0ef41Sopenharmony_ci 18461cb0ef41Sopenharmony_civoid Assembler::ddivu(Register rs, Register rt) { 18471cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DDIVU); 18481cb0ef41Sopenharmony_ci} 18491cb0ef41Sopenharmony_ci 18501cb0ef41Sopenharmony_civoid Assembler::ddivu(Register rd, Register rs, Register rt) { 18511cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 18521cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, D_DIV_MOD_U); 18531cb0ef41Sopenharmony_ci} 18541cb0ef41Sopenharmony_ci 18551cb0ef41Sopenharmony_civoid Assembler::dmodu(Register rd, Register rs, Register rt) { 18561cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 18571cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, D_DIV_MOD_U); 18581cb0ef41Sopenharmony_ci} 18591cb0ef41Sopenharmony_ci 18601cb0ef41Sopenharmony_ci// Logical. 18611cb0ef41Sopenharmony_ci 18621cb0ef41Sopenharmony_civoid Assembler::and_(Register rd, Register rs, Register rt) { 18631cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND); 18641cb0ef41Sopenharmony_ci} 18651cb0ef41Sopenharmony_ci 18661cb0ef41Sopenharmony_civoid Assembler::andi(Register rt, Register rs, int32_t j) { 18671cb0ef41Sopenharmony_ci DCHECK(is_uint16(j)); 18681cb0ef41Sopenharmony_ci GenInstrImmediate(ANDI, rs, rt, j); 18691cb0ef41Sopenharmony_ci} 18701cb0ef41Sopenharmony_ci 18711cb0ef41Sopenharmony_civoid Assembler::or_(Register rd, Register rs, Register rt) { 18721cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, OR); 18731cb0ef41Sopenharmony_ci} 18741cb0ef41Sopenharmony_ci 18751cb0ef41Sopenharmony_civoid Assembler::ori(Register rt, Register rs, int32_t j) { 18761cb0ef41Sopenharmony_ci DCHECK(is_uint16(j)); 18771cb0ef41Sopenharmony_ci GenInstrImmediate(ORI, rs, rt, j); 18781cb0ef41Sopenharmony_ci} 18791cb0ef41Sopenharmony_ci 18801cb0ef41Sopenharmony_civoid Assembler::xor_(Register rd, Register rs, Register rt) { 18811cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, XOR); 18821cb0ef41Sopenharmony_ci} 18831cb0ef41Sopenharmony_ci 18841cb0ef41Sopenharmony_civoid Assembler::xori(Register rt, Register rs, int32_t j) { 18851cb0ef41Sopenharmony_ci DCHECK(is_uint16(j)); 18861cb0ef41Sopenharmony_ci GenInstrImmediate(XORI, rs, rt, j); 18871cb0ef41Sopenharmony_ci} 18881cb0ef41Sopenharmony_ci 18891cb0ef41Sopenharmony_civoid Assembler::nor(Register rd, Register rs, Register rt) { 18901cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, NOR); 18911cb0ef41Sopenharmony_ci} 18921cb0ef41Sopenharmony_ci 18931cb0ef41Sopenharmony_ci// Shifts. 18941cb0ef41Sopenharmony_civoid Assembler::sll(Register rd, Register rt, uint16_t sa, 18951cb0ef41Sopenharmony_ci bool coming_from_nop) { 18961cb0ef41Sopenharmony_ci // Don't allow nop instructions in the form sll zero_reg, zero_reg to be 18971cb0ef41Sopenharmony_ci // generated using the sll instruction. They must be generated using 18981cb0ef41Sopenharmony_ci // nop(int/NopMarkerTypes). 18991cb0ef41Sopenharmony_ci DCHECK(coming_from_nop || (rd != zero_reg && rt != zero_reg)); 19001cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SLL); 19011cb0ef41Sopenharmony_ci} 19021cb0ef41Sopenharmony_ci 19031cb0ef41Sopenharmony_civoid Assembler::sllv(Register rd, Register rt, Register rs) { 19041cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLLV); 19051cb0ef41Sopenharmony_ci} 19061cb0ef41Sopenharmony_ci 19071cb0ef41Sopenharmony_civoid Assembler::srl(Register rd, Register rt, uint16_t sa) { 19081cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRL); 19091cb0ef41Sopenharmony_ci} 19101cb0ef41Sopenharmony_ci 19111cb0ef41Sopenharmony_civoid Assembler::srlv(Register rd, Register rt, Register rs) { 19121cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRLV); 19131cb0ef41Sopenharmony_ci} 19141cb0ef41Sopenharmony_ci 19151cb0ef41Sopenharmony_civoid Assembler::sra(Register rd, Register rt, uint16_t sa) { 19161cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, SRA); 19171cb0ef41Sopenharmony_ci} 19181cb0ef41Sopenharmony_ci 19191cb0ef41Sopenharmony_civoid Assembler::srav(Register rd, Register rt, Register rs) { 19201cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV); 19211cb0ef41Sopenharmony_ci} 19221cb0ef41Sopenharmony_ci 19231cb0ef41Sopenharmony_civoid Assembler::rotr(Register rd, Register rt, uint16_t sa) { 19241cb0ef41Sopenharmony_ci // Should be called via MacroAssembler::Ror. 19251cb0ef41Sopenharmony_ci DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa)); 19261cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 19271cb0ef41Sopenharmony_ci Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) | 19281cb0ef41Sopenharmony_ci (rd.code() << kRdShift) | (sa << kSaShift) | SRL; 19291cb0ef41Sopenharmony_ci emit(instr); 19301cb0ef41Sopenharmony_ci} 19311cb0ef41Sopenharmony_ci 19321cb0ef41Sopenharmony_civoid Assembler::rotrv(Register rd, Register rt, Register rs) { 19331cb0ef41Sopenharmony_ci // Should be called via MacroAssembler::Ror. 19341cb0ef41Sopenharmony_ci DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid()); 19351cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 19361cb0ef41Sopenharmony_ci Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) | 19371cb0ef41Sopenharmony_ci (rd.code() << kRdShift) | (1 << kSaShift) | SRLV; 19381cb0ef41Sopenharmony_ci emit(instr); 19391cb0ef41Sopenharmony_ci} 19401cb0ef41Sopenharmony_ci 19411cb0ef41Sopenharmony_civoid Assembler::dsll(Register rd, Register rt, uint16_t sa) { 19421cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSLL); 19431cb0ef41Sopenharmony_ci} 19441cb0ef41Sopenharmony_ci 19451cb0ef41Sopenharmony_civoid Assembler::dsllv(Register rd, Register rt, Register rs) { 19461cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSLLV); 19471cb0ef41Sopenharmony_ci} 19481cb0ef41Sopenharmony_ci 19491cb0ef41Sopenharmony_civoid Assembler::dsrl(Register rd, Register rt, uint16_t sa) { 19501cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRL); 19511cb0ef41Sopenharmony_ci} 19521cb0ef41Sopenharmony_ci 19531cb0ef41Sopenharmony_civoid Assembler::dsrlv(Register rd, Register rt, Register rs) { 19541cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRLV); 19551cb0ef41Sopenharmony_ci} 19561cb0ef41Sopenharmony_ci 19571cb0ef41Sopenharmony_civoid Assembler::drotr(Register rd, Register rt, uint16_t sa) { 19581cb0ef41Sopenharmony_ci DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa)); 19591cb0ef41Sopenharmony_ci Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) | 19601cb0ef41Sopenharmony_ci (rd.code() << kRdShift) | (sa << kSaShift) | DSRL; 19611cb0ef41Sopenharmony_ci emit(instr); 19621cb0ef41Sopenharmony_ci} 19631cb0ef41Sopenharmony_ci 19641cb0ef41Sopenharmony_civoid Assembler::drotr32(Register rd, Register rt, uint16_t sa) { 19651cb0ef41Sopenharmony_ci DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa)); 19661cb0ef41Sopenharmony_ci Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) | 19671cb0ef41Sopenharmony_ci (rd.code() << kRdShift) | (sa << kSaShift) | DSRL32; 19681cb0ef41Sopenharmony_ci emit(instr); 19691cb0ef41Sopenharmony_ci} 19701cb0ef41Sopenharmony_ci 19711cb0ef41Sopenharmony_civoid Assembler::drotrv(Register rd, Register rt, Register rs) { 19721cb0ef41Sopenharmony_ci DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid()); 19731cb0ef41Sopenharmony_ci Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) | 19741cb0ef41Sopenharmony_ci (rd.code() << kRdShift) | (1 << kSaShift) | DSRLV; 19751cb0ef41Sopenharmony_ci emit(instr); 19761cb0ef41Sopenharmony_ci} 19771cb0ef41Sopenharmony_ci 19781cb0ef41Sopenharmony_civoid Assembler::dsra(Register rd, Register rt, uint16_t sa) { 19791cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRA); 19801cb0ef41Sopenharmony_ci} 19811cb0ef41Sopenharmony_ci 19821cb0ef41Sopenharmony_civoid Assembler::dsrav(Register rd, Register rt, Register rs) { 19831cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, DSRAV); 19841cb0ef41Sopenharmony_ci} 19851cb0ef41Sopenharmony_ci 19861cb0ef41Sopenharmony_civoid Assembler::dsll32(Register rd, Register rt, uint16_t sa) { 19871cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSLL32); 19881cb0ef41Sopenharmony_ci} 19891cb0ef41Sopenharmony_ci 19901cb0ef41Sopenharmony_civoid Assembler::dsrl32(Register rd, Register rt, uint16_t sa) { 19911cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRL32); 19921cb0ef41Sopenharmony_ci} 19931cb0ef41Sopenharmony_ci 19941cb0ef41Sopenharmony_civoid Assembler::dsra32(Register rd, Register rt, uint16_t sa) { 19951cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, zero_reg, rt, rd, sa & 0x1F, DSRA32); 19961cb0ef41Sopenharmony_ci} 19971cb0ef41Sopenharmony_ci 19981cb0ef41Sopenharmony_civoid Assembler::lsa(Register rd, Register rt, Register rs, uint8_t sa) { 19991cb0ef41Sopenharmony_ci DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid()); 20001cb0ef41Sopenharmony_ci DCHECK_LE(sa, 3); 20011cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 20021cb0ef41Sopenharmony_ci Instr instr = SPECIAL | rs.code() << kRsShift | rt.code() << kRtShift | 20031cb0ef41Sopenharmony_ci rd.code() << kRdShift | sa << kSaShift | LSA; 20041cb0ef41Sopenharmony_ci emit(instr); 20051cb0ef41Sopenharmony_ci} 20061cb0ef41Sopenharmony_ci 20071cb0ef41Sopenharmony_civoid Assembler::dlsa(Register rd, Register rt, Register rs, uint8_t sa) { 20081cb0ef41Sopenharmony_ci DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid()); 20091cb0ef41Sopenharmony_ci DCHECK_LE(sa, 3); 20101cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 20111cb0ef41Sopenharmony_ci Instr instr = SPECIAL | rs.code() << kRsShift | rt.code() << kRtShift | 20121cb0ef41Sopenharmony_ci rd.code() << kRdShift | sa << kSaShift | DLSA; 20131cb0ef41Sopenharmony_ci emit(instr); 20141cb0ef41Sopenharmony_ci} 20151cb0ef41Sopenharmony_ci 20161cb0ef41Sopenharmony_ci// ------------Memory-instructions------------- 20171cb0ef41Sopenharmony_ci 20181cb0ef41Sopenharmony_civoid Assembler::AdjustBaseAndOffset(MemOperand* src, 20191cb0ef41Sopenharmony_ci OffsetAccessType access_type, 20201cb0ef41Sopenharmony_ci int second_access_add_to_offset) { 20211cb0ef41Sopenharmony_ci // This method is used to adjust the base register and offset pair 20221cb0ef41Sopenharmony_ci // for a load/store when the offset doesn't fit into int16_t. 20231cb0ef41Sopenharmony_ci // It is assumed that 'base + offset' is sufficiently aligned for memory 20241cb0ef41Sopenharmony_ci // operands that are machine word in size or smaller. For doubleword-sized 20251cb0ef41Sopenharmony_ci // operands it's assumed that 'base' is a multiple of 8, while 'offset' 20261cb0ef41Sopenharmony_ci // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments 20271cb0ef41Sopenharmony_ci // and spilled variables on the stack accessed relative to the stack 20281cb0ef41Sopenharmony_ci // pointer register). 20291cb0ef41Sopenharmony_ci // We preserve the "alignment" of 'offset' by adjusting it by a multiple of 8. 20301cb0ef41Sopenharmony_ci 20311cb0ef41Sopenharmony_ci bool doubleword_aligned = (src->offset() & (kDoubleSize - 1)) == 0; 20321cb0ef41Sopenharmony_ci bool two_accesses = static_cast<bool>(access_type) || !doubleword_aligned; 20331cb0ef41Sopenharmony_ci DCHECK_LE(second_access_add_to_offset, 7); // Must be <= 7. 20341cb0ef41Sopenharmony_ci 20351cb0ef41Sopenharmony_ci // is_int16 must be passed a signed value, hence the static cast below. 20361cb0ef41Sopenharmony_ci if (is_int16(src->offset()) && 20371cb0ef41Sopenharmony_ci (!two_accesses || is_int16(static_cast<int32_t>( 20381cb0ef41Sopenharmony_ci src->offset() + second_access_add_to_offset)))) { 20391cb0ef41Sopenharmony_ci // Nothing to do: 'offset' (and, if needed, 'offset + 4', or other specified 20401cb0ef41Sopenharmony_ci // value) fits into int16_t. 20411cb0ef41Sopenharmony_ci return; 20421cb0ef41Sopenharmony_ci } 20431cb0ef41Sopenharmony_ci 20441cb0ef41Sopenharmony_ci DCHECK(src->rm() != 20451cb0ef41Sopenharmony_ci at); // Must not overwrite the register 'base' while loading 'offset'. 20461cb0ef41Sopenharmony_ci 20471cb0ef41Sopenharmony_ci#ifdef DEBUG 20481cb0ef41Sopenharmony_ci // Remember the "(mis)alignment" of 'offset', it will be checked at the end. 20491cb0ef41Sopenharmony_ci uint32_t misalignment = src->offset() & (kDoubleSize - 1); 20501cb0ef41Sopenharmony_ci#endif 20511cb0ef41Sopenharmony_ci 20521cb0ef41Sopenharmony_ci // Do not load the whole 32-bit 'offset' if it can be represented as 20531cb0ef41Sopenharmony_ci // a sum of two 16-bit signed offsets. This can save an instruction or two. 20541cb0ef41Sopenharmony_ci // To simplify matters, only do this for a symmetric range of offsets from 20551cb0ef41Sopenharmony_ci // about -64KB to about +64KB, allowing further addition of 4 when accessing 20561cb0ef41Sopenharmony_ci // 64-bit variables with two 32-bit accesses. 20571cb0ef41Sopenharmony_ci constexpr int32_t kMinOffsetForSimpleAdjustment = 20581cb0ef41Sopenharmony_ci 0x7FF8; // Max int16_t that's a multiple of 8. 20591cb0ef41Sopenharmony_ci constexpr int32_t kMaxOffsetForSimpleAdjustment = 20601cb0ef41Sopenharmony_ci 2 * kMinOffsetForSimpleAdjustment; 20611cb0ef41Sopenharmony_ci 20621cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 20631cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 20641cb0ef41Sopenharmony_ci if (0 <= src->offset() && src->offset() <= kMaxOffsetForSimpleAdjustment) { 20651cb0ef41Sopenharmony_ci daddiu(scratch, src->rm(), kMinOffsetForSimpleAdjustment); 20661cb0ef41Sopenharmony_ci src->offset_ -= kMinOffsetForSimpleAdjustment; 20671cb0ef41Sopenharmony_ci } else if (-kMaxOffsetForSimpleAdjustment <= src->offset() && 20681cb0ef41Sopenharmony_ci src->offset() < 0) { 20691cb0ef41Sopenharmony_ci daddiu(scratch, src->rm(), -kMinOffsetForSimpleAdjustment); 20701cb0ef41Sopenharmony_ci src->offset_ += kMinOffsetForSimpleAdjustment; 20711cb0ef41Sopenharmony_ci } else if (kArchVariant == kMips64r6) { 20721cb0ef41Sopenharmony_ci // On r6 take advantage of the daui instruction, e.g.: 20731cb0ef41Sopenharmony_ci // daui at, base, offset_high 20741cb0ef41Sopenharmony_ci // [dahi at, 1] // When `offset` is close to +2GB. 20751cb0ef41Sopenharmony_ci // lw reg_lo, offset_low(at) 20761cb0ef41Sopenharmony_ci // [lw reg_hi, (offset_low+4)(at)] // If misaligned 64-bit load. 20771cb0ef41Sopenharmony_ci // or when offset_low+4 overflows int16_t: 20781cb0ef41Sopenharmony_ci // daui at, base, offset_high 20791cb0ef41Sopenharmony_ci // daddiu at, at, 8 20801cb0ef41Sopenharmony_ci // lw reg_lo, (offset_low-8)(at) 20811cb0ef41Sopenharmony_ci // lw reg_hi, (offset_low-4)(at) 20821cb0ef41Sopenharmony_ci int16_t offset_low = static_cast<uint16_t>(src->offset()); 20831cb0ef41Sopenharmony_ci int32_t offset_low32 = offset_low; 20841cb0ef41Sopenharmony_ci int16_t offset_high = static_cast<uint16_t>(src->offset() >> 16); 20851cb0ef41Sopenharmony_ci bool increment_hi16 = offset_low < 0; 20861cb0ef41Sopenharmony_ci bool overflow_hi16 = false; 20871cb0ef41Sopenharmony_ci 20881cb0ef41Sopenharmony_ci if (increment_hi16) { 20891cb0ef41Sopenharmony_ci offset_high++; 20901cb0ef41Sopenharmony_ci overflow_hi16 = (offset_high == -32768); 20911cb0ef41Sopenharmony_ci } 20921cb0ef41Sopenharmony_ci daui(scratch, src->rm(), static_cast<uint16_t>(offset_high)); 20931cb0ef41Sopenharmony_ci 20941cb0ef41Sopenharmony_ci if (overflow_hi16) { 20951cb0ef41Sopenharmony_ci dahi(scratch, 1); 20961cb0ef41Sopenharmony_ci } 20971cb0ef41Sopenharmony_ci 20981cb0ef41Sopenharmony_ci if (two_accesses && !is_int16(static_cast<int32_t>( 20991cb0ef41Sopenharmony_ci offset_low32 + second_access_add_to_offset))) { 21001cb0ef41Sopenharmony_ci // Avoid overflow in the 16-bit offset of the load/store instruction when 21011cb0ef41Sopenharmony_ci // adding 4. 21021cb0ef41Sopenharmony_ci daddiu(scratch, scratch, kDoubleSize); 21031cb0ef41Sopenharmony_ci offset_low32 -= kDoubleSize; 21041cb0ef41Sopenharmony_ci } 21051cb0ef41Sopenharmony_ci 21061cb0ef41Sopenharmony_ci src->offset_ = offset_low32; 21071cb0ef41Sopenharmony_ci } else { 21081cb0ef41Sopenharmony_ci // Do not load the whole 32-bit 'offset' if it can be represented as 21091cb0ef41Sopenharmony_ci // a sum of three 16-bit signed offsets. This can save an instruction. 21101cb0ef41Sopenharmony_ci // To simplify matters, only do this for a symmetric range of offsets from 21111cb0ef41Sopenharmony_ci // about -96KB to about +96KB, allowing further addition of 4 when accessing 21121cb0ef41Sopenharmony_ci // 64-bit variables with two 32-bit accesses. 21131cb0ef41Sopenharmony_ci constexpr int32_t kMinOffsetForMediumAdjustment = 21141cb0ef41Sopenharmony_ci 2 * kMinOffsetForSimpleAdjustment; 21151cb0ef41Sopenharmony_ci constexpr int32_t kMaxOffsetForMediumAdjustment = 21161cb0ef41Sopenharmony_ci 3 * kMinOffsetForSimpleAdjustment; 21171cb0ef41Sopenharmony_ci if (0 <= src->offset() && src->offset() <= kMaxOffsetForMediumAdjustment) { 21181cb0ef41Sopenharmony_ci daddiu(scratch, src->rm(), kMinOffsetForMediumAdjustment / 2); 21191cb0ef41Sopenharmony_ci daddiu(scratch, scratch, kMinOffsetForMediumAdjustment / 2); 21201cb0ef41Sopenharmony_ci src->offset_ -= kMinOffsetForMediumAdjustment; 21211cb0ef41Sopenharmony_ci } else if (-kMaxOffsetForMediumAdjustment <= src->offset() && 21221cb0ef41Sopenharmony_ci src->offset() < 0) { 21231cb0ef41Sopenharmony_ci daddiu(scratch, src->rm(), -kMinOffsetForMediumAdjustment / 2); 21241cb0ef41Sopenharmony_ci daddiu(scratch, scratch, -kMinOffsetForMediumAdjustment / 2); 21251cb0ef41Sopenharmony_ci src->offset_ += kMinOffsetForMediumAdjustment; 21261cb0ef41Sopenharmony_ci } else { 21271cb0ef41Sopenharmony_ci // Now that all shorter options have been exhausted, load the full 32-bit 21281cb0ef41Sopenharmony_ci // offset. 21291cb0ef41Sopenharmony_ci int32_t loaded_offset = RoundDown(src->offset(), kDoubleSize); 21301cb0ef41Sopenharmony_ci lui(scratch, (loaded_offset >> kLuiShift) & kImm16Mask); 21311cb0ef41Sopenharmony_ci ori(scratch, scratch, loaded_offset & kImm16Mask); // Load 32-bit offset. 21321cb0ef41Sopenharmony_ci daddu(scratch, scratch, src->rm()); 21331cb0ef41Sopenharmony_ci src->offset_ -= loaded_offset; 21341cb0ef41Sopenharmony_ci } 21351cb0ef41Sopenharmony_ci } 21361cb0ef41Sopenharmony_ci src->rm_ = scratch; 21371cb0ef41Sopenharmony_ci 21381cb0ef41Sopenharmony_ci DCHECK(is_int16(src->offset())); 21391cb0ef41Sopenharmony_ci if (two_accesses) { 21401cb0ef41Sopenharmony_ci DCHECK(is_int16( 21411cb0ef41Sopenharmony_ci static_cast<int32_t>(src->offset() + second_access_add_to_offset))); 21421cb0ef41Sopenharmony_ci } 21431cb0ef41Sopenharmony_ci DCHECK(misalignment == (src->offset() & (kDoubleSize - 1))); 21441cb0ef41Sopenharmony_ci} 21451cb0ef41Sopenharmony_ci 21461cb0ef41Sopenharmony_civoid Assembler::lb(Register rd, const MemOperand& rs) { 21471cb0ef41Sopenharmony_ci GenInstrImmediate(LB, rs.rm(), rd, rs.offset_); 21481cb0ef41Sopenharmony_ci} 21491cb0ef41Sopenharmony_ci 21501cb0ef41Sopenharmony_civoid Assembler::lbu(Register rd, const MemOperand& rs) { 21511cb0ef41Sopenharmony_ci GenInstrImmediate(LBU, rs.rm(), rd, rs.offset_); 21521cb0ef41Sopenharmony_ci} 21531cb0ef41Sopenharmony_ci 21541cb0ef41Sopenharmony_civoid Assembler::lh(Register rd, const MemOperand& rs) { 21551cb0ef41Sopenharmony_ci GenInstrImmediate(LH, rs.rm(), rd, rs.offset_); 21561cb0ef41Sopenharmony_ci} 21571cb0ef41Sopenharmony_ci 21581cb0ef41Sopenharmony_civoid Assembler::lhu(Register rd, const MemOperand& rs) { 21591cb0ef41Sopenharmony_ci GenInstrImmediate(LHU, rs.rm(), rd, rs.offset_); 21601cb0ef41Sopenharmony_ci} 21611cb0ef41Sopenharmony_ci 21621cb0ef41Sopenharmony_civoid Assembler::lw(Register rd, const MemOperand& rs) { 21631cb0ef41Sopenharmony_ci GenInstrImmediate(LW, rs.rm(), rd, rs.offset_); 21641cb0ef41Sopenharmony_ci} 21651cb0ef41Sopenharmony_ci 21661cb0ef41Sopenharmony_civoid Assembler::lwu(Register rd, const MemOperand& rs) { 21671cb0ef41Sopenharmony_ci GenInstrImmediate(LWU, rs.rm(), rd, rs.offset_); 21681cb0ef41Sopenharmony_ci} 21691cb0ef41Sopenharmony_ci 21701cb0ef41Sopenharmony_civoid Assembler::lwl(Register rd, const MemOperand& rs) { 21711cb0ef41Sopenharmony_ci DCHECK(is_int16(rs.offset_)); 21721cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 21731cb0ef41Sopenharmony_ci GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_); 21741cb0ef41Sopenharmony_ci} 21751cb0ef41Sopenharmony_ci 21761cb0ef41Sopenharmony_civoid Assembler::lwr(Register rd, const MemOperand& rs) { 21771cb0ef41Sopenharmony_ci DCHECK(is_int16(rs.offset_)); 21781cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 21791cb0ef41Sopenharmony_ci GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_); 21801cb0ef41Sopenharmony_ci} 21811cb0ef41Sopenharmony_ci 21821cb0ef41Sopenharmony_civoid Assembler::sb(Register rd, const MemOperand& rs) { 21831cb0ef41Sopenharmony_ci GenInstrImmediate(SB, rs.rm(), rd, rs.offset_); 21841cb0ef41Sopenharmony_ci} 21851cb0ef41Sopenharmony_ci 21861cb0ef41Sopenharmony_civoid Assembler::sh(Register rd, const MemOperand& rs) { 21871cb0ef41Sopenharmony_ci GenInstrImmediate(SH, rs.rm(), rd, rs.offset_); 21881cb0ef41Sopenharmony_ci} 21891cb0ef41Sopenharmony_ci 21901cb0ef41Sopenharmony_civoid Assembler::sw(Register rd, const MemOperand& rs) { 21911cb0ef41Sopenharmony_ci GenInstrImmediate(SW, rs.rm(), rd, rs.offset_); 21921cb0ef41Sopenharmony_ci} 21931cb0ef41Sopenharmony_ci 21941cb0ef41Sopenharmony_civoid Assembler::swl(Register rd, const MemOperand& rs) { 21951cb0ef41Sopenharmony_ci DCHECK(is_int16(rs.offset_)); 21961cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 21971cb0ef41Sopenharmony_ci GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_); 21981cb0ef41Sopenharmony_ci} 21991cb0ef41Sopenharmony_ci 22001cb0ef41Sopenharmony_civoid Assembler::swr(Register rd, const MemOperand& rs) { 22011cb0ef41Sopenharmony_ci DCHECK(is_int16(rs.offset_)); 22021cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 22031cb0ef41Sopenharmony_ci GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_); 22041cb0ef41Sopenharmony_ci} 22051cb0ef41Sopenharmony_ci 22061cb0ef41Sopenharmony_civoid Assembler::ll(Register rd, const MemOperand& rs) { 22071cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 22081cb0ef41Sopenharmony_ci DCHECK(is_int9(rs.offset_)); 22091cb0ef41Sopenharmony_ci GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, LL_R6); 22101cb0ef41Sopenharmony_ci } else { 22111cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 22121cb0ef41Sopenharmony_ci DCHECK(is_int16(rs.offset_)); 22131cb0ef41Sopenharmony_ci GenInstrImmediate(LL, rs.rm(), rd, rs.offset_); 22141cb0ef41Sopenharmony_ci } 22151cb0ef41Sopenharmony_ci} 22161cb0ef41Sopenharmony_ci 22171cb0ef41Sopenharmony_civoid Assembler::lld(Register rd, const MemOperand& rs) { 22181cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 22191cb0ef41Sopenharmony_ci DCHECK(is_int9(rs.offset_)); 22201cb0ef41Sopenharmony_ci GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, LLD_R6); 22211cb0ef41Sopenharmony_ci } else { 22221cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 22231cb0ef41Sopenharmony_ci DCHECK(is_int16(rs.offset_)); 22241cb0ef41Sopenharmony_ci GenInstrImmediate(LLD, rs.rm(), rd, rs.offset_); 22251cb0ef41Sopenharmony_ci } 22261cb0ef41Sopenharmony_ci} 22271cb0ef41Sopenharmony_ci 22281cb0ef41Sopenharmony_civoid Assembler::sc(Register rd, const MemOperand& rs) { 22291cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 22301cb0ef41Sopenharmony_ci DCHECK(is_int9(rs.offset_)); 22311cb0ef41Sopenharmony_ci GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, SC_R6); 22321cb0ef41Sopenharmony_ci } else { 22331cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 22341cb0ef41Sopenharmony_ci GenInstrImmediate(SC, rs.rm(), rd, rs.offset_); 22351cb0ef41Sopenharmony_ci } 22361cb0ef41Sopenharmony_ci} 22371cb0ef41Sopenharmony_ci 22381cb0ef41Sopenharmony_civoid Assembler::scd(Register rd, const MemOperand& rs) { 22391cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 22401cb0ef41Sopenharmony_ci DCHECK(is_int9(rs.offset_)); 22411cb0ef41Sopenharmony_ci GenInstrImmediate(SPECIAL3, rs.rm(), rd, rs.offset_, 0, SCD_R6); 22421cb0ef41Sopenharmony_ci } else { 22431cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 22441cb0ef41Sopenharmony_ci GenInstrImmediate(SCD, rs.rm(), rd, rs.offset_); 22451cb0ef41Sopenharmony_ci } 22461cb0ef41Sopenharmony_ci} 22471cb0ef41Sopenharmony_ci 22481cb0ef41Sopenharmony_civoid Assembler::lui(Register rd, int32_t j) { 22491cb0ef41Sopenharmony_ci DCHECK(is_uint16(j) || is_int16(j)); 22501cb0ef41Sopenharmony_ci GenInstrImmediate(LUI, zero_reg, rd, j); 22511cb0ef41Sopenharmony_ci} 22521cb0ef41Sopenharmony_ci 22531cb0ef41Sopenharmony_civoid Assembler::aui(Register rt, Register rs, int32_t j) { 22541cb0ef41Sopenharmony_ci // This instruction uses same opcode as 'lui'. The difference in encoding is 22551cb0ef41Sopenharmony_ci // 'lui' has zero reg. for rs field. 22561cb0ef41Sopenharmony_ci DCHECK(is_uint16(j)); 22571cb0ef41Sopenharmony_ci GenInstrImmediate(LUI, rs, rt, j); 22581cb0ef41Sopenharmony_ci} 22591cb0ef41Sopenharmony_ci 22601cb0ef41Sopenharmony_civoid Assembler::daui(Register rt, Register rs, int32_t j) { 22611cb0ef41Sopenharmony_ci DCHECK(is_uint16(j)); 22621cb0ef41Sopenharmony_ci DCHECK(rs != zero_reg); 22631cb0ef41Sopenharmony_ci GenInstrImmediate(DAUI, rs, rt, j); 22641cb0ef41Sopenharmony_ci} 22651cb0ef41Sopenharmony_ci 22661cb0ef41Sopenharmony_civoid Assembler::dahi(Register rs, int32_t j) { 22671cb0ef41Sopenharmony_ci DCHECK(is_uint16(j)); 22681cb0ef41Sopenharmony_ci GenInstrImmediate(REGIMM, rs, DAHI, j); 22691cb0ef41Sopenharmony_ci} 22701cb0ef41Sopenharmony_ci 22711cb0ef41Sopenharmony_civoid Assembler::dati(Register rs, int32_t j) { 22721cb0ef41Sopenharmony_ci DCHECK(is_uint16(j)); 22731cb0ef41Sopenharmony_ci GenInstrImmediate(REGIMM, rs, DATI, j); 22741cb0ef41Sopenharmony_ci} 22751cb0ef41Sopenharmony_ci 22761cb0ef41Sopenharmony_civoid Assembler::ldl(Register rd, const MemOperand& rs) { 22771cb0ef41Sopenharmony_ci DCHECK(is_int16(rs.offset_)); 22781cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 22791cb0ef41Sopenharmony_ci GenInstrImmediate(LDL, rs.rm(), rd, rs.offset_); 22801cb0ef41Sopenharmony_ci} 22811cb0ef41Sopenharmony_ci 22821cb0ef41Sopenharmony_civoid Assembler::ldr(Register rd, const MemOperand& rs) { 22831cb0ef41Sopenharmony_ci DCHECK(is_int16(rs.offset_)); 22841cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 22851cb0ef41Sopenharmony_ci GenInstrImmediate(LDR, rs.rm(), rd, rs.offset_); 22861cb0ef41Sopenharmony_ci} 22871cb0ef41Sopenharmony_ci 22881cb0ef41Sopenharmony_civoid Assembler::sdl(Register rd, const MemOperand& rs) { 22891cb0ef41Sopenharmony_ci DCHECK(is_int16(rs.offset_)); 22901cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 22911cb0ef41Sopenharmony_ci GenInstrImmediate(SDL, rs.rm(), rd, rs.offset_); 22921cb0ef41Sopenharmony_ci} 22931cb0ef41Sopenharmony_ci 22941cb0ef41Sopenharmony_civoid Assembler::sdr(Register rd, const MemOperand& rs) { 22951cb0ef41Sopenharmony_ci DCHECK(is_int16(rs.offset_)); 22961cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 22971cb0ef41Sopenharmony_ci GenInstrImmediate(SDR, rs.rm(), rd, rs.offset_); 22981cb0ef41Sopenharmony_ci} 22991cb0ef41Sopenharmony_ci 23001cb0ef41Sopenharmony_civoid Assembler::ld(Register rd, const MemOperand& rs) { 23011cb0ef41Sopenharmony_ci GenInstrImmediate(LD, rs.rm(), rd, rs.offset_); 23021cb0ef41Sopenharmony_ci} 23031cb0ef41Sopenharmony_ci 23041cb0ef41Sopenharmony_civoid Assembler::sd(Register rd, const MemOperand& rs) { 23051cb0ef41Sopenharmony_ci GenInstrImmediate(SD, rs.rm(), rd, rs.offset_); 23061cb0ef41Sopenharmony_ci} 23071cb0ef41Sopenharmony_ci 23081cb0ef41Sopenharmony_ci// ---------PC-Relative instructions----------- 23091cb0ef41Sopenharmony_ci 23101cb0ef41Sopenharmony_civoid Assembler::addiupc(Register rs, int32_t imm19) { 23111cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 23121cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && is_int19(imm19)); 23131cb0ef41Sopenharmony_ci uint32_t imm21 = ADDIUPC << kImm19Bits | (imm19 & kImm19Mask); 23141cb0ef41Sopenharmony_ci GenInstrImmediate(PCREL, rs, imm21); 23151cb0ef41Sopenharmony_ci} 23161cb0ef41Sopenharmony_ci 23171cb0ef41Sopenharmony_civoid Assembler::lwpc(Register rs, int32_t offset19) { 23181cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 23191cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && is_int19(offset19)); 23201cb0ef41Sopenharmony_ci uint32_t imm21 = LWPC << kImm19Bits | (offset19 & kImm19Mask); 23211cb0ef41Sopenharmony_ci GenInstrImmediate(PCREL, rs, imm21); 23221cb0ef41Sopenharmony_ci} 23231cb0ef41Sopenharmony_ci 23241cb0ef41Sopenharmony_civoid Assembler::lwupc(Register rs, int32_t offset19) { 23251cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 23261cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && is_int19(offset19)); 23271cb0ef41Sopenharmony_ci uint32_t imm21 = LWUPC << kImm19Bits | (offset19 & kImm19Mask); 23281cb0ef41Sopenharmony_ci GenInstrImmediate(PCREL, rs, imm21); 23291cb0ef41Sopenharmony_ci} 23301cb0ef41Sopenharmony_ci 23311cb0ef41Sopenharmony_civoid Assembler::ldpc(Register rs, int32_t offset18) { 23321cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 23331cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && is_int18(offset18)); 23341cb0ef41Sopenharmony_ci uint32_t imm21 = LDPC << kImm18Bits | (offset18 & kImm18Mask); 23351cb0ef41Sopenharmony_ci GenInstrImmediate(PCREL, rs, imm21); 23361cb0ef41Sopenharmony_ci} 23371cb0ef41Sopenharmony_ci 23381cb0ef41Sopenharmony_civoid Assembler::auipc(Register rs, int16_t imm16) { 23391cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 23401cb0ef41Sopenharmony_ci DCHECK(rs.is_valid()); 23411cb0ef41Sopenharmony_ci uint32_t imm21 = AUIPC << kImm16Bits | (imm16 & kImm16Mask); 23421cb0ef41Sopenharmony_ci GenInstrImmediate(PCREL, rs, imm21); 23431cb0ef41Sopenharmony_ci} 23441cb0ef41Sopenharmony_ci 23451cb0ef41Sopenharmony_civoid Assembler::aluipc(Register rs, int16_t imm16) { 23461cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 23471cb0ef41Sopenharmony_ci DCHECK(rs.is_valid()); 23481cb0ef41Sopenharmony_ci uint32_t imm21 = ALUIPC << kImm16Bits | (imm16 & kImm16Mask); 23491cb0ef41Sopenharmony_ci GenInstrImmediate(PCREL, rs, imm21); 23501cb0ef41Sopenharmony_ci} 23511cb0ef41Sopenharmony_ci 23521cb0ef41Sopenharmony_ci// -------------Misc-instructions-------------- 23531cb0ef41Sopenharmony_ci 23541cb0ef41Sopenharmony_ci// Break / Trap instructions. 23551cb0ef41Sopenharmony_civoid Assembler::break_(uint32_t code, bool break_as_stop) { 23561cb0ef41Sopenharmony_ci DCHECK_EQ(code & ~0xFFFFF, 0); 23571cb0ef41Sopenharmony_ci // We need to invalidate breaks that could be stops as well because the 23581cb0ef41Sopenharmony_ci // simulator expects a char pointer after the stop instruction. 23591cb0ef41Sopenharmony_ci // See constants-mips.h for explanation. 23601cb0ef41Sopenharmony_ci DCHECK( 23611cb0ef41Sopenharmony_ci (break_as_stop && code <= kMaxStopCode && code > kMaxWatchpointCode) || 23621cb0ef41Sopenharmony_ci (!break_as_stop && (code > kMaxStopCode || code <= kMaxWatchpointCode))); 23631cb0ef41Sopenharmony_ci Instr break_instr = SPECIAL | BREAK | (code << 6); 23641cb0ef41Sopenharmony_ci emit(break_instr); 23651cb0ef41Sopenharmony_ci} 23661cb0ef41Sopenharmony_ci 23671cb0ef41Sopenharmony_civoid Assembler::stop(uint32_t code) { 23681cb0ef41Sopenharmony_ci DCHECK_GT(code, kMaxWatchpointCode); 23691cb0ef41Sopenharmony_ci DCHECK_LE(code, kMaxStopCode); 23701cb0ef41Sopenharmony_ci#if defined(V8_HOST_ARCH_MIPS) || defined(V8_HOST_ARCH_MIPS64) 23711cb0ef41Sopenharmony_ci break_(0x54321); 23721cb0ef41Sopenharmony_ci#else // V8_HOST_ARCH_MIPS 23731cb0ef41Sopenharmony_ci break_(code, true); 23741cb0ef41Sopenharmony_ci#endif 23751cb0ef41Sopenharmony_ci} 23761cb0ef41Sopenharmony_ci 23771cb0ef41Sopenharmony_civoid Assembler::tge(Register rs, Register rt, uint16_t code) { 23781cb0ef41Sopenharmony_ci DCHECK(is_uint10(code)); 23791cb0ef41Sopenharmony_ci Instr instr = 23801cb0ef41Sopenharmony_ci SPECIAL | TGE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6; 23811cb0ef41Sopenharmony_ci emit(instr); 23821cb0ef41Sopenharmony_ci} 23831cb0ef41Sopenharmony_ci 23841cb0ef41Sopenharmony_civoid Assembler::tgeu(Register rs, Register rt, uint16_t code) { 23851cb0ef41Sopenharmony_ci DCHECK(is_uint10(code)); 23861cb0ef41Sopenharmony_ci Instr instr = SPECIAL | TGEU | rs.code() << kRsShift | rt.code() << kRtShift | 23871cb0ef41Sopenharmony_ci code << 6; 23881cb0ef41Sopenharmony_ci emit(instr); 23891cb0ef41Sopenharmony_ci} 23901cb0ef41Sopenharmony_ci 23911cb0ef41Sopenharmony_civoid Assembler::tlt(Register rs, Register rt, uint16_t code) { 23921cb0ef41Sopenharmony_ci DCHECK(is_uint10(code)); 23931cb0ef41Sopenharmony_ci Instr instr = 23941cb0ef41Sopenharmony_ci SPECIAL | TLT | rs.code() << kRsShift | rt.code() << kRtShift | code << 6; 23951cb0ef41Sopenharmony_ci emit(instr); 23961cb0ef41Sopenharmony_ci} 23971cb0ef41Sopenharmony_ci 23981cb0ef41Sopenharmony_civoid Assembler::tltu(Register rs, Register rt, uint16_t code) { 23991cb0ef41Sopenharmony_ci DCHECK(is_uint10(code)); 24001cb0ef41Sopenharmony_ci Instr instr = SPECIAL | TLTU | rs.code() << kRsShift | rt.code() << kRtShift | 24011cb0ef41Sopenharmony_ci code << 6; 24021cb0ef41Sopenharmony_ci emit(instr); 24031cb0ef41Sopenharmony_ci} 24041cb0ef41Sopenharmony_ci 24051cb0ef41Sopenharmony_civoid Assembler::teq(Register rs, Register rt, uint16_t code) { 24061cb0ef41Sopenharmony_ci DCHECK(is_uint10(code)); 24071cb0ef41Sopenharmony_ci Instr instr = 24081cb0ef41Sopenharmony_ci SPECIAL | TEQ | rs.code() << kRsShift | rt.code() << kRtShift | code << 6; 24091cb0ef41Sopenharmony_ci emit(instr); 24101cb0ef41Sopenharmony_ci} 24111cb0ef41Sopenharmony_ci 24121cb0ef41Sopenharmony_civoid Assembler::tne(Register rs, Register rt, uint16_t code) { 24131cb0ef41Sopenharmony_ci DCHECK(is_uint10(code)); 24141cb0ef41Sopenharmony_ci Instr instr = 24151cb0ef41Sopenharmony_ci SPECIAL | TNE | rs.code() << kRsShift | rt.code() << kRtShift | code << 6; 24161cb0ef41Sopenharmony_ci emit(instr); 24171cb0ef41Sopenharmony_ci} 24181cb0ef41Sopenharmony_ci 24191cb0ef41Sopenharmony_civoid Assembler::sync() { 24201cb0ef41Sopenharmony_ci Instr sync_instr = SPECIAL | SYNC; 24211cb0ef41Sopenharmony_ci emit(sync_instr); 24221cb0ef41Sopenharmony_ci} 24231cb0ef41Sopenharmony_ci 24241cb0ef41Sopenharmony_ci// Move from HI/LO register. 24251cb0ef41Sopenharmony_ci 24261cb0ef41Sopenharmony_civoid Assembler::mfhi(Register rd) { 24271cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFHI); 24281cb0ef41Sopenharmony_ci} 24291cb0ef41Sopenharmony_ci 24301cb0ef41Sopenharmony_civoid Assembler::mflo(Register rd) { 24311cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, zero_reg, zero_reg, rd, 0, MFLO); 24321cb0ef41Sopenharmony_ci} 24331cb0ef41Sopenharmony_ci 24341cb0ef41Sopenharmony_ci// Set on less than instructions. 24351cb0ef41Sopenharmony_civoid Assembler::slt(Register rd, Register rs, Register rt) { 24361cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLT); 24371cb0ef41Sopenharmony_ci} 24381cb0ef41Sopenharmony_ci 24391cb0ef41Sopenharmony_civoid Assembler::sltu(Register rd, Register rs, Register rt) { 24401cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, SLTU); 24411cb0ef41Sopenharmony_ci} 24421cb0ef41Sopenharmony_ci 24431cb0ef41Sopenharmony_civoid Assembler::slti(Register rt, Register rs, int32_t j) { 24441cb0ef41Sopenharmony_ci GenInstrImmediate(SLTI, rs, rt, j); 24451cb0ef41Sopenharmony_ci} 24461cb0ef41Sopenharmony_ci 24471cb0ef41Sopenharmony_civoid Assembler::sltiu(Register rt, Register rs, int32_t j) { 24481cb0ef41Sopenharmony_ci GenInstrImmediate(SLTIU, rs, rt, j); 24491cb0ef41Sopenharmony_ci} 24501cb0ef41Sopenharmony_ci 24511cb0ef41Sopenharmony_ci// Conditional move. 24521cb0ef41Sopenharmony_civoid Assembler::movz(Register rd, Register rs, Register rt) { 24531cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVZ); 24541cb0ef41Sopenharmony_ci} 24551cb0ef41Sopenharmony_ci 24561cb0ef41Sopenharmony_civoid Assembler::movn(Register rd, Register rs, Register rt) { 24571cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVN); 24581cb0ef41Sopenharmony_ci} 24591cb0ef41Sopenharmony_ci 24601cb0ef41Sopenharmony_civoid Assembler::movt(Register rd, Register rs, uint16_t cc) { 24611cb0ef41Sopenharmony_ci Register rt = Register::from_code((cc & 0x0007) << 2 | 1); 24621cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); 24631cb0ef41Sopenharmony_ci} 24641cb0ef41Sopenharmony_ci 24651cb0ef41Sopenharmony_civoid Assembler::movf(Register rd, Register rs, uint16_t cc) { 24661cb0ef41Sopenharmony_ci Register rt = Register::from_code((cc & 0x0007) << 2 | 0); 24671cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); 24681cb0ef41Sopenharmony_ci} 24691cb0ef41Sopenharmony_ci 24701cb0ef41Sopenharmony_civoid Assembler::min_s(FPURegister fd, FPURegister fs, FPURegister ft) { 24711cb0ef41Sopenharmony_ci min(S, fd, fs, ft); 24721cb0ef41Sopenharmony_ci} 24731cb0ef41Sopenharmony_ci 24741cb0ef41Sopenharmony_civoid Assembler::min_d(FPURegister fd, FPURegister fs, FPURegister ft) { 24751cb0ef41Sopenharmony_ci min(D, fd, fs, ft); 24761cb0ef41Sopenharmony_ci} 24771cb0ef41Sopenharmony_ci 24781cb0ef41Sopenharmony_civoid Assembler::max_s(FPURegister fd, FPURegister fs, FPURegister ft) { 24791cb0ef41Sopenharmony_ci max(S, fd, fs, ft); 24801cb0ef41Sopenharmony_ci} 24811cb0ef41Sopenharmony_ci 24821cb0ef41Sopenharmony_civoid Assembler::max_d(FPURegister fd, FPURegister fs, FPURegister ft) { 24831cb0ef41Sopenharmony_ci max(D, fd, fs, ft); 24841cb0ef41Sopenharmony_ci} 24851cb0ef41Sopenharmony_ci 24861cb0ef41Sopenharmony_civoid Assembler::mina_s(FPURegister fd, FPURegister fs, FPURegister ft) { 24871cb0ef41Sopenharmony_ci mina(S, fd, fs, ft); 24881cb0ef41Sopenharmony_ci} 24891cb0ef41Sopenharmony_ci 24901cb0ef41Sopenharmony_civoid Assembler::mina_d(FPURegister fd, FPURegister fs, FPURegister ft) { 24911cb0ef41Sopenharmony_ci mina(D, fd, fs, ft); 24921cb0ef41Sopenharmony_ci} 24931cb0ef41Sopenharmony_ci 24941cb0ef41Sopenharmony_civoid Assembler::maxa_s(FPURegister fd, FPURegister fs, FPURegister ft) { 24951cb0ef41Sopenharmony_ci maxa(S, fd, fs, ft); 24961cb0ef41Sopenharmony_ci} 24971cb0ef41Sopenharmony_ci 24981cb0ef41Sopenharmony_civoid Assembler::maxa_d(FPURegister fd, FPURegister fs, FPURegister ft) { 24991cb0ef41Sopenharmony_ci maxa(D, fd, fs, ft); 25001cb0ef41Sopenharmony_ci} 25011cb0ef41Sopenharmony_ci 25021cb0ef41Sopenharmony_civoid Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister fs, 25031cb0ef41Sopenharmony_ci FPURegister ft) { 25041cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 25051cb0ef41Sopenharmony_ci DCHECK((fmt == D) || (fmt == S)); 25061cb0ef41Sopenharmony_ci GenInstrRegister(COP1, fmt, ft, fs, fd, MAX); 25071cb0ef41Sopenharmony_ci} 25081cb0ef41Sopenharmony_ci 25091cb0ef41Sopenharmony_civoid Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister fs, 25101cb0ef41Sopenharmony_ci FPURegister ft) { 25111cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 25121cb0ef41Sopenharmony_ci DCHECK((fmt == D) || (fmt == S)); 25131cb0ef41Sopenharmony_ci GenInstrRegister(COP1, fmt, ft, fs, fd, MIN); 25141cb0ef41Sopenharmony_ci} 25151cb0ef41Sopenharmony_ci 25161cb0ef41Sopenharmony_ci// GPR. 25171cb0ef41Sopenharmony_civoid Assembler::seleqz(Register rd, Register rs, Register rt) { 25181cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 25191cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELEQZ_S); 25201cb0ef41Sopenharmony_ci} 25211cb0ef41Sopenharmony_ci 25221cb0ef41Sopenharmony_ci// GPR. 25231cb0ef41Sopenharmony_civoid Assembler::selnez(Register rd, Register rs, Register rt) { 25241cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 25251cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, rt, rd, 0, SELNEZ_S); 25261cb0ef41Sopenharmony_ci} 25271cb0ef41Sopenharmony_ci 25281cb0ef41Sopenharmony_ci// Bit twiddling. 25291cb0ef41Sopenharmony_civoid Assembler::clz(Register rd, Register rs) { 25301cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 25311cb0ef41Sopenharmony_ci // clz instr requires same GPR number in 'rd' and 'rt' fields. 25321cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ); 25331cb0ef41Sopenharmony_ci } else { 25341cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, CLZ_R6); 25351cb0ef41Sopenharmony_ci } 25361cb0ef41Sopenharmony_ci} 25371cb0ef41Sopenharmony_ci 25381cb0ef41Sopenharmony_civoid Assembler::dclz(Register rd, Register rs) { 25391cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 25401cb0ef41Sopenharmony_ci // dclz instr requires same GPR number in 'rd' and 'rt' fields. 25411cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL2, rs, rd, rd, 0, DCLZ); 25421cb0ef41Sopenharmony_ci } else { 25431cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, DCLZ_R6); 25441cb0ef41Sopenharmony_ci } 25451cb0ef41Sopenharmony_ci} 25461cb0ef41Sopenharmony_ci 25471cb0ef41Sopenharmony_civoid Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) { 25481cb0ef41Sopenharmony_ci // Should be called via MacroAssembler::Ins. 25491cb0ef41Sopenharmony_ci // ins instr has 'rt' field as dest, and two uint5: msb, lsb. 25501cb0ef41Sopenharmony_ci DCHECK((kArchVariant == kMips64r2) || (kArchVariant == kMips64r6)); 25511cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS); 25521cb0ef41Sopenharmony_ci} 25531cb0ef41Sopenharmony_ci 25541cb0ef41Sopenharmony_civoid Assembler::dins_(Register rt, Register rs, uint16_t pos, uint16_t size) { 25551cb0ef41Sopenharmony_ci // Should be called via MacroAssembler::Dins. 25561cb0ef41Sopenharmony_ci // dins instr has 'rt' field as dest, and two uint5: msb, lsb. 25571cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 25581cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, DINS); 25591cb0ef41Sopenharmony_ci} 25601cb0ef41Sopenharmony_ci 25611cb0ef41Sopenharmony_civoid Assembler::dinsm_(Register rt, Register rs, uint16_t pos, uint16_t size) { 25621cb0ef41Sopenharmony_ci // Should be called via MacroAssembler::Dins. 25631cb0ef41Sopenharmony_ci // dinsm instr has 'rt' field as dest, and two uint5: msbminus32, lsb. 25641cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 25651cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1 - 32, pos, DINSM); 25661cb0ef41Sopenharmony_ci} 25671cb0ef41Sopenharmony_ci 25681cb0ef41Sopenharmony_civoid Assembler::dinsu_(Register rt, Register rs, uint16_t pos, uint16_t size) { 25691cb0ef41Sopenharmony_ci // Should be called via MacroAssembler::Dins. 25701cb0ef41Sopenharmony_ci // dinsu instr has 'rt' field as dest, and two uint5: msbminus32, lsbminus32. 25711cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 25721cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1 - 32, pos - 32, DINSU); 25731cb0ef41Sopenharmony_ci} 25741cb0ef41Sopenharmony_ci 25751cb0ef41Sopenharmony_civoid Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) { 25761cb0ef41Sopenharmony_ci // Should be called via MacroAssembler::Ext. 25771cb0ef41Sopenharmony_ci // ext instr has 'rt' field as dest, and two uint5: msbd, lsb. 25781cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 25791cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT); 25801cb0ef41Sopenharmony_ci} 25811cb0ef41Sopenharmony_ci 25821cb0ef41Sopenharmony_civoid Assembler::dext_(Register rt, Register rs, uint16_t pos, uint16_t size) { 25831cb0ef41Sopenharmony_ci // Should be called via MacroAssembler::Dext. 25841cb0ef41Sopenharmony_ci // dext instr has 'rt' field as dest, and two uint5: msbd, lsb. 25851cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 25861cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, DEXT); 25871cb0ef41Sopenharmony_ci} 25881cb0ef41Sopenharmony_ci 25891cb0ef41Sopenharmony_civoid Assembler::dextm_(Register rt, Register rs, uint16_t pos, uint16_t size) { 25901cb0ef41Sopenharmony_ci // Should be called via MacroAssembler::Dextm. 25911cb0ef41Sopenharmony_ci // dextm instr has 'rt' field as dest, and two uint5: msbdminus32, lsb. 25921cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 25931cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, rs, rt, size - 1 - 32, pos, DEXTM); 25941cb0ef41Sopenharmony_ci} 25951cb0ef41Sopenharmony_ci 25961cb0ef41Sopenharmony_civoid Assembler::dextu_(Register rt, Register rs, uint16_t pos, uint16_t size) { 25971cb0ef41Sopenharmony_ci // Should be called via MacroAssembler::Dextu. 25981cb0ef41Sopenharmony_ci // dextu instr has 'rt' field as dest, and two uint5: msbd, lsbminus32. 25991cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 26001cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos - 32, DEXTU); 26011cb0ef41Sopenharmony_ci} 26021cb0ef41Sopenharmony_ci 26031cb0ef41Sopenharmony_civoid Assembler::bitswap(Register rd, Register rt) { 26041cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 26051cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, BSHFL); 26061cb0ef41Sopenharmony_ci} 26071cb0ef41Sopenharmony_ci 26081cb0ef41Sopenharmony_civoid Assembler::dbitswap(Register rd, Register rt) { 26091cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 26101cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, zero_reg, rt, rd, 0, DBSHFL); 26111cb0ef41Sopenharmony_ci} 26121cb0ef41Sopenharmony_ci 26131cb0ef41Sopenharmony_civoid Assembler::pref(int32_t hint, const MemOperand& rs) { 26141cb0ef41Sopenharmony_ci DCHECK(is_uint5(hint) && is_uint16(rs.offset_)); 26151cb0ef41Sopenharmony_ci Instr instr = 26161cb0ef41Sopenharmony_ci PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift) | (rs.offset_); 26171cb0ef41Sopenharmony_ci emit(instr); 26181cb0ef41Sopenharmony_ci} 26191cb0ef41Sopenharmony_ci 26201cb0ef41Sopenharmony_civoid Assembler::align(Register rd, Register rs, Register rt, uint8_t bp) { 26211cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 26221cb0ef41Sopenharmony_ci DCHECK(is_uint3(bp)); 26231cb0ef41Sopenharmony_ci uint16_t sa = (ALIGN << kBp2Bits) | bp; 26241cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, rs, rt, rd, sa, BSHFL); 26251cb0ef41Sopenharmony_ci} 26261cb0ef41Sopenharmony_ci 26271cb0ef41Sopenharmony_civoid Assembler::dalign(Register rd, Register rs, Register rt, uint8_t bp) { 26281cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 26291cb0ef41Sopenharmony_ci DCHECK(is_uint3(bp)); 26301cb0ef41Sopenharmony_ci uint16_t sa = (DALIGN << kBp3Bits) | bp; 26311cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, rs, rt, rd, sa, DBSHFL); 26321cb0ef41Sopenharmony_ci} 26331cb0ef41Sopenharmony_ci 26341cb0ef41Sopenharmony_civoid Assembler::wsbh(Register rd, Register rt) { 26351cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 26361cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, zero_reg, rt, rd, WSBH, BSHFL); 26371cb0ef41Sopenharmony_ci} 26381cb0ef41Sopenharmony_ci 26391cb0ef41Sopenharmony_civoid Assembler::dsbh(Register rd, Register rt) { 26401cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 26411cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSBH, DBSHFL); 26421cb0ef41Sopenharmony_ci} 26431cb0ef41Sopenharmony_ci 26441cb0ef41Sopenharmony_civoid Assembler::dshd(Register rd, Register rt) { 26451cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 26461cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, zero_reg, rt, rd, DSHD, DBSHFL); 26471cb0ef41Sopenharmony_ci} 26481cb0ef41Sopenharmony_ci 26491cb0ef41Sopenharmony_civoid Assembler::seh(Register rd, Register rt) { 26501cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 26511cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEH, BSHFL); 26521cb0ef41Sopenharmony_ci} 26531cb0ef41Sopenharmony_ci 26541cb0ef41Sopenharmony_civoid Assembler::seb(Register rd, Register rt) { 26551cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 26561cb0ef41Sopenharmony_ci GenInstrRegister(SPECIAL3, zero_reg, rt, rd, SEB, BSHFL); 26571cb0ef41Sopenharmony_ci} 26581cb0ef41Sopenharmony_ci 26591cb0ef41Sopenharmony_ci// --------Coprocessor-instructions---------------- 26601cb0ef41Sopenharmony_ci 26611cb0ef41Sopenharmony_ci// Load, store, move. 26621cb0ef41Sopenharmony_civoid Assembler::lwc1(FPURegister fd, const MemOperand& src) { 26631cb0ef41Sopenharmony_ci GenInstrImmediate(LWC1, src.rm(), fd, src.offset_); 26641cb0ef41Sopenharmony_ci} 26651cb0ef41Sopenharmony_ci 26661cb0ef41Sopenharmony_civoid Assembler::ldc1(FPURegister fd, const MemOperand& src) { 26671cb0ef41Sopenharmony_ci GenInstrImmediate(LDC1, src.rm(), fd, src.offset_); 26681cb0ef41Sopenharmony_ci} 26691cb0ef41Sopenharmony_ci 26701cb0ef41Sopenharmony_civoid Assembler::swc1(FPURegister fs, const MemOperand& src) { 26711cb0ef41Sopenharmony_ci GenInstrImmediate(SWC1, src.rm(), fs, src.offset_); 26721cb0ef41Sopenharmony_ci} 26731cb0ef41Sopenharmony_ci 26741cb0ef41Sopenharmony_civoid Assembler::sdc1(FPURegister fs, const MemOperand& src) { 26751cb0ef41Sopenharmony_ci GenInstrImmediate(SDC1, src.rm(), fs, src.offset_); 26761cb0ef41Sopenharmony_ci} 26771cb0ef41Sopenharmony_ci 26781cb0ef41Sopenharmony_civoid Assembler::mtc1(Register rt, FPURegister fs) { 26791cb0ef41Sopenharmony_ci GenInstrRegister(COP1, MTC1, rt, fs, f0); 26801cb0ef41Sopenharmony_ci} 26811cb0ef41Sopenharmony_ci 26821cb0ef41Sopenharmony_civoid Assembler::mthc1(Register rt, FPURegister fs) { 26831cb0ef41Sopenharmony_ci GenInstrRegister(COP1, MTHC1, rt, fs, f0); 26841cb0ef41Sopenharmony_ci} 26851cb0ef41Sopenharmony_ci 26861cb0ef41Sopenharmony_civoid Assembler::dmtc1(Register rt, FPURegister fs) { 26871cb0ef41Sopenharmony_ci GenInstrRegister(COP1, DMTC1, rt, fs, f0); 26881cb0ef41Sopenharmony_ci} 26891cb0ef41Sopenharmony_ci 26901cb0ef41Sopenharmony_civoid Assembler::mfc1(Register rt, FPURegister fs) { 26911cb0ef41Sopenharmony_ci GenInstrRegister(COP1, MFC1, rt, fs, f0); 26921cb0ef41Sopenharmony_ci} 26931cb0ef41Sopenharmony_ci 26941cb0ef41Sopenharmony_civoid Assembler::mfhc1(Register rt, FPURegister fs) { 26951cb0ef41Sopenharmony_ci GenInstrRegister(COP1, MFHC1, rt, fs, f0); 26961cb0ef41Sopenharmony_ci} 26971cb0ef41Sopenharmony_ci 26981cb0ef41Sopenharmony_civoid Assembler::dmfc1(Register rt, FPURegister fs) { 26991cb0ef41Sopenharmony_ci GenInstrRegister(COP1, DMFC1, rt, fs, f0); 27001cb0ef41Sopenharmony_ci} 27011cb0ef41Sopenharmony_ci 27021cb0ef41Sopenharmony_civoid Assembler::ctc1(Register rt, FPUControlRegister fs) { 27031cb0ef41Sopenharmony_ci GenInstrRegister(COP1, CTC1, rt, fs); 27041cb0ef41Sopenharmony_ci} 27051cb0ef41Sopenharmony_ci 27061cb0ef41Sopenharmony_civoid Assembler::cfc1(Register rt, FPUControlRegister fs) { 27071cb0ef41Sopenharmony_ci GenInstrRegister(COP1, CFC1, rt, fs); 27081cb0ef41Sopenharmony_ci} 27091cb0ef41Sopenharmony_ci 27101cb0ef41Sopenharmony_civoid Assembler::sel(SecondaryField fmt, FPURegister fd, FPURegister fs, 27111cb0ef41Sopenharmony_ci FPURegister ft) { 27121cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 27131cb0ef41Sopenharmony_ci DCHECK((fmt == D) || (fmt == S)); 27141cb0ef41Sopenharmony_ci 27151cb0ef41Sopenharmony_ci GenInstrRegister(COP1, fmt, ft, fs, fd, SEL); 27161cb0ef41Sopenharmony_ci} 27171cb0ef41Sopenharmony_ci 27181cb0ef41Sopenharmony_civoid Assembler::sel_s(FPURegister fd, FPURegister fs, FPURegister ft) { 27191cb0ef41Sopenharmony_ci sel(S, fd, fs, ft); 27201cb0ef41Sopenharmony_ci} 27211cb0ef41Sopenharmony_ci 27221cb0ef41Sopenharmony_civoid Assembler::sel_d(FPURegister fd, FPURegister fs, FPURegister ft) { 27231cb0ef41Sopenharmony_ci sel(D, fd, fs, ft); 27241cb0ef41Sopenharmony_ci} 27251cb0ef41Sopenharmony_ci 27261cb0ef41Sopenharmony_ci// FPR. 27271cb0ef41Sopenharmony_civoid Assembler::seleqz(SecondaryField fmt, FPURegister fd, FPURegister fs, 27281cb0ef41Sopenharmony_ci FPURegister ft) { 27291cb0ef41Sopenharmony_ci DCHECK((fmt == D) || (fmt == S)); 27301cb0ef41Sopenharmony_ci GenInstrRegister(COP1, fmt, ft, fs, fd, SELEQZ_C); 27311cb0ef41Sopenharmony_ci} 27321cb0ef41Sopenharmony_ci 27331cb0ef41Sopenharmony_civoid Assembler::seleqz_d(FPURegister fd, FPURegister fs, FPURegister ft) { 27341cb0ef41Sopenharmony_ci seleqz(D, fd, fs, ft); 27351cb0ef41Sopenharmony_ci} 27361cb0ef41Sopenharmony_ci 27371cb0ef41Sopenharmony_civoid Assembler::seleqz_s(FPURegister fd, FPURegister fs, FPURegister ft) { 27381cb0ef41Sopenharmony_ci seleqz(S, fd, fs, ft); 27391cb0ef41Sopenharmony_ci} 27401cb0ef41Sopenharmony_ci 27411cb0ef41Sopenharmony_civoid Assembler::selnez_d(FPURegister fd, FPURegister fs, FPURegister ft) { 27421cb0ef41Sopenharmony_ci selnez(D, fd, fs, ft); 27431cb0ef41Sopenharmony_ci} 27441cb0ef41Sopenharmony_ci 27451cb0ef41Sopenharmony_civoid Assembler::selnez_s(FPURegister fd, FPURegister fs, FPURegister ft) { 27461cb0ef41Sopenharmony_ci selnez(S, fd, fs, ft); 27471cb0ef41Sopenharmony_ci} 27481cb0ef41Sopenharmony_ci 27491cb0ef41Sopenharmony_civoid Assembler::movz_s(FPURegister fd, FPURegister fs, Register rt) { 27501cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 27511cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, rt, fs, fd, MOVZ_C); 27521cb0ef41Sopenharmony_ci} 27531cb0ef41Sopenharmony_ci 27541cb0ef41Sopenharmony_civoid Assembler::movz_d(FPURegister fd, FPURegister fs, Register rt) { 27551cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 27561cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, rt, fs, fd, MOVZ_C); 27571cb0ef41Sopenharmony_ci} 27581cb0ef41Sopenharmony_ci 27591cb0ef41Sopenharmony_civoid Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) { 27601cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 27611cb0ef41Sopenharmony_ci FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 1); 27621cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, ft, fs, fd, MOVF); 27631cb0ef41Sopenharmony_ci} 27641cb0ef41Sopenharmony_ci 27651cb0ef41Sopenharmony_civoid Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) { 27661cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 27671cb0ef41Sopenharmony_ci FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 1); 27681cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, ft, fs, fd, MOVF); 27691cb0ef41Sopenharmony_ci} 27701cb0ef41Sopenharmony_ci 27711cb0ef41Sopenharmony_civoid Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) { 27721cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 27731cb0ef41Sopenharmony_ci FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 0); 27741cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, ft, fs, fd, MOVF); 27751cb0ef41Sopenharmony_ci} 27761cb0ef41Sopenharmony_ci 27771cb0ef41Sopenharmony_civoid Assembler::movf_d(FPURegister fd, FPURegister fs, uint16_t cc) { 27781cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 27791cb0ef41Sopenharmony_ci FPURegister ft = FPURegister::from_code((cc & 0x0007) << 2 | 0); 27801cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, ft, fs, fd, MOVF); 27811cb0ef41Sopenharmony_ci} 27821cb0ef41Sopenharmony_ci 27831cb0ef41Sopenharmony_civoid Assembler::movn_s(FPURegister fd, FPURegister fs, Register rt) { 27841cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 27851cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, rt, fs, fd, MOVN_C); 27861cb0ef41Sopenharmony_ci} 27871cb0ef41Sopenharmony_ci 27881cb0ef41Sopenharmony_civoid Assembler::movn_d(FPURegister fd, FPURegister fs, Register rt) { 27891cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 27901cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, rt, fs, fd, MOVN_C); 27911cb0ef41Sopenharmony_ci} 27921cb0ef41Sopenharmony_ci 27931cb0ef41Sopenharmony_ci// FPR. 27941cb0ef41Sopenharmony_civoid Assembler::selnez(SecondaryField fmt, FPURegister fd, FPURegister fs, 27951cb0ef41Sopenharmony_ci FPURegister ft) { 27961cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 27971cb0ef41Sopenharmony_ci DCHECK((fmt == D) || (fmt == S)); 27981cb0ef41Sopenharmony_ci GenInstrRegister(COP1, fmt, ft, fs, fd, SELNEZ_C); 27991cb0ef41Sopenharmony_ci} 28001cb0ef41Sopenharmony_ci 28011cb0ef41Sopenharmony_ci// Arithmetic. 28021cb0ef41Sopenharmony_ci 28031cb0ef41Sopenharmony_civoid Assembler::add_s(FPURegister fd, FPURegister fs, FPURegister ft) { 28041cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, ft, fs, fd, ADD_D); 28051cb0ef41Sopenharmony_ci} 28061cb0ef41Sopenharmony_ci 28071cb0ef41Sopenharmony_civoid Assembler::add_d(FPURegister fd, FPURegister fs, FPURegister ft) { 28081cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, ft, fs, fd, ADD_D); 28091cb0ef41Sopenharmony_ci} 28101cb0ef41Sopenharmony_ci 28111cb0ef41Sopenharmony_civoid Assembler::sub_s(FPURegister fd, FPURegister fs, FPURegister ft) { 28121cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, ft, fs, fd, SUB_D); 28131cb0ef41Sopenharmony_ci} 28141cb0ef41Sopenharmony_ci 28151cb0ef41Sopenharmony_civoid Assembler::sub_d(FPURegister fd, FPURegister fs, FPURegister ft) { 28161cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, ft, fs, fd, SUB_D); 28171cb0ef41Sopenharmony_ci} 28181cb0ef41Sopenharmony_ci 28191cb0ef41Sopenharmony_civoid Assembler::mul_s(FPURegister fd, FPURegister fs, FPURegister ft) { 28201cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, ft, fs, fd, MUL_D); 28211cb0ef41Sopenharmony_ci} 28221cb0ef41Sopenharmony_ci 28231cb0ef41Sopenharmony_civoid Assembler::mul_d(FPURegister fd, FPURegister fs, FPURegister ft) { 28241cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, ft, fs, fd, MUL_D); 28251cb0ef41Sopenharmony_ci} 28261cb0ef41Sopenharmony_ci 28271cb0ef41Sopenharmony_civoid Assembler::madd_s(FPURegister fd, FPURegister fr, FPURegister fs, 28281cb0ef41Sopenharmony_ci FPURegister ft) { 28291cb0ef41Sopenharmony_ci // On Loongson 3A (MIPS64R2), MADD.S instruction is actually fused MADD.S and 28301cb0ef41Sopenharmony_ci // this causes failure in some of the tests. Since this optimization is rarely 28311cb0ef41Sopenharmony_ci // used, and not used at all on MIPS64R6, this isntruction is removed. 28321cb0ef41Sopenharmony_ci UNREACHABLE(); 28331cb0ef41Sopenharmony_ci} 28341cb0ef41Sopenharmony_ci 28351cb0ef41Sopenharmony_civoid Assembler::madd_d(FPURegister fd, FPURegister fr, FPURegister fs, 28361cb0ef41Sopenharmony_ci FPURegister ft) { 28371cb0ef41Sopenharmony_ci // On Loongson 3A (MIPS64R2), MADD.D instruction is actually fused MADD.D and 28381cb0ef41Sopenharmony_ci // this causes failure in some of the tests. Since this optimization is rarely 28391cb0ef41Sopenharmony_ci // used, and not used at all on MIPS64R6, this isntruction is removed. 28401cb0ef41Sopenharmony_ci UNREACHABLE(); 28411cb0ef41Sopenharmony_ci} 28421cb0ef41Sopenharmony_ci 28431cb0ef41Sopenharmony_civoid Assembler::msub_s(FPURegister fd, FPURegister fr, FPURegister fs, 28441cb0ef41Sopenharmony_ci FPURegister ft) { 28451cb0ef41Sopenharmony_ci // See explanation for instruction madd_s. 28461cb0ef41Sopenharmony_ci UNREACHABLE(); 28471cb0ef41Sopenharmony_ci} 28481cb0ef41Sopenharmony_ci 28491cb0ef41Sopenharmony_civoid Assembler::msub_d(FPURegister fd, FPURegister fr, FPURegister fs, 28501cb0ef41Sopenharmony_ci FPURegister ft) { 28511cb0ef41Sopenharmony_ci // See explanation for instruction madd_d. 28521cb0ef41Sopenharmony_ci UNREACHABLE(); 28531cb0ef41Sopenharmony_ci} 28541cb0ef41Sopenharmony_ci 28551cb0ef41Sopenharmony_civoid Assembler::maddf_s(FPURegister fd, FPURegister fs, FPURegister ft) { 28561cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 28571cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, ft, fs, fd, MADDF_S); 28581cb0ef41Sopenharmony_ci} 28591cb0ef41Sopenharmony_ci 28601cb0ef41Sopenharmony_civoid Assembler::maddf_d(FPURegister fd, FPURegister fs, FPURegister ft) { 28611cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 28621cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, ft, fs, fd, MADDF_D); 28631cb0ef41Sopenharmony_ci} 28641cb0ef41Sopenharmony_ci 28651cb0ef41Sopenharmony_civoid Assembler::msubf_s(FPURegister fd, FPURegister fs, FPURegister ft) { 28661cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 28671cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, ft, fs, fd, MSUBF_S); 28681cb0ef41Sopenharmony_ci} 28691cb0ef41Sopenharmony_ci 28701cb0ef41Sopenharmony_civoid Assembler::msubf_d(FPURegister fd, FPURegister fs, FPURegister ft) { 28711cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 28721cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, ft, fs, fd, MSUBF_D); 28731cb0ef41Sopenharmony_ci} 28741cb0ef41Sopenharmony_ci 28751cb0ef41Sopenharmony_civoid Assembler::div_s(FPURegister fd, FPURegister fs, FPURegister ft) { 28761cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, ft, fs, fd, DIV_D); 28771cb0ef41Sopenharmony_ci} 28781cb0ef41Sopenharmony_ci 28791cb0ef41Sopenharmony_civoid Assembler::div_d(FPURegister fd, FPURegister fs, FPURegister ft) { 28801cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, ft, fs, fd, DIV_D); 28811cb0ef41Sopenharmony_ci} 28821cb0ef41Sopenharmony_ci 28831cb0ef41Sopenharmony_civoid Assembler::abs_s(FPURegister fd, FPURegister fs) { 28841cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, ABS_D); 28851cb0ef41Sopenharmony_ci} 28861cb0ef41Sopenharmony_ci 28871cb0ef41Sopenharmony_civoid Assembler::abs_d(FPURegister fd, FPURegister fs) { 28881cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, ABS_D); 28891cb0ef41Sopenharmony_ci} 28901cb0ef41Sopenharmony_ci 28911cb0ef41Sopenharmony_civoid Assembler::mov_d(FPURegister fd, FPURegister fs) { 28921cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, MOV_D); 28931cb0ef41Sopenharmony_ci} 28941cb0ef41Sopenharmony_ci 28951cb0ef41Sopenharmony_civoid Assembler::mov_s(FPURegister fd, FPURegister fs) { 28961cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, MOV_S); 28971cb0ef41Sopenharmony_ci} 28981cb0ef41Sopenharmony_ci 28991cb0ef41Sopenharmony_civoid Assembler::neg_s(FPURegister fd, FPURegister fs) { 29001cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, NEG_D); 29011cb0ef41Sopenharmony_ci} 29021cb0ef41Sopenharmony_ci 29031cb0ef41Sopenharmony_civoid Assembler::neg_d(FPURegister fd, FPURegister fs) { 29041cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, NEG_D); 29051cb0ef41Sopenharmony_ci} 29061cb0ef41Sopenharmony_ci 29071cb0ef41Sopenharmony_civoid Assembler::sqrt_s(FPURegister fd, FPURegister fs) { 29081cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, SQRT_D); 29091cb0ef41Sopenharmony_ci} 29101cb0ef41Sopenharmony_ci 29111cb0ef41Sopenharmony_civoid Assembler::sqrt_d(FPURegister fd, FPURegister fs) { 29121cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, SQRT_D); 29131cb0ef41Sopenharmony_ci} 29141cb0ef41Sopenharmony_ci 29151cb0ef41Sopenharmony_civoid Assembler::rsqrt_s(FPURegister fd, FPURegister fs) { 29161cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, RSQRT_S); 29171cb0ef41Sopenharmony_ci} 29181cb0ef41Sopenharmony_ci 29191cb0ef41Sopenharmony_civoid Assembler::rsqrt_d(FPURegister fd, FPURegister fs) { 29201cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, RSQRT_D); 29211cb0ef41Sopenharmony_ci} 29221cb0ef41Sopenharmony_ci 29231cb0ef41Sopenharmony_civoid Assembler::recip_d(FPURegister fd, FPURegister fs) { 29241cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, RECIP_D); 29251cb0ef41Sopenharmony_ci} 29261cb0ef41Sopenharmony_ci 29271cb0ef41Sopenharmony_civoid Assembler::recip_s(FPURegister fd, FPURegister fs) { 29281cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, RECIP_S); 29291cb0ef41Sopenharmony_ci} 29301cb0ef41Sopenharmony_ci 29311cb0ef41Sopenharmony_ci// Conversions. 29321cb0ef41Sopenharmony_civoid Assembler::cvt_w_s(FPURegister fd, FPURegister fs) { 29331cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, CVT_W_S); 29341cb0ef41Sopenharmony_ci} 29351cb0ef41Sopenharmony_ci 29361cb0ef41Sopenharmony_civoid Assembler::cvt_w_d(FPURegister fd, FPURegister fs) { 29371cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, CVT_W_D); 29381cb0ef41Sopenharmony_ci} 29391cb0ef41Sopenharmony_ci 29401cb0ef41Sopenharmony_civoid Assembler::trunc_w_s(FPURegister fd, FPURegister fs) { 29411cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_W_S); 29421cb0ef41Sopenharmony_ci} 29431cb0ef41Sopenharmony_ci 29441cb0ef41Sopenharmony_civoid Assembler::trunc_w_d(FPURegister fd, FPURegister fs) { 29451cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_W_D); 29461cb0ef41Sopenharmony_ci} 29471cb0ef41Sopenharmony_ci 29481cb0ef41Sopenharmony_civoid Assembler::round_w_s(FPURegister fd, FPURegister fs) { 29491cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, ROUND_W_S); 29501cb0ef41Sopenharmony_ci} 29511cb0ef41Sopenharmony_ci 29521cb0ef41Sopenharmony_civoid Assembler::round_w_d(FPURegister fd, FPURegister fs) { 29531cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, ROUND_W_D); 29541cb0ef41Sopenharmony_ci} 29551cb0ef41Sopenharmony_ci 29561cb0ef41Sopenharmony_civoid Assembler::floor_w_s(FPURegister fd, FPURegister fs) { 29571cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_W_S); 29581cb0ef41Sopenharmony_ci} 29591cb0ef41Sopenharmony_ci 29601cb0ef41Sopenharmony_civoid Assembler::floor_w_d(FPURegister fd, FPURegister fs) { 29611cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_W_D); 29621cb0ef41Sopenharmony_ci} 29631cb0ef41Sopenharmony_ci 29641cb0ef41Sopenharmony_civoid Assembler::ceil_w_s(FPURegister fd, FPURegister fs) { 29651cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S); 29661cb0ef41Sopenharmony_ci} 29671cb0ef41Sopenharmony_ci 29681cb0ef41Sopenharmony_civoid Assembler::ceil_w_d(FPURegister fd, FPURegister fs) { 29691cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D); 29701cb0ef41Sopenharmony_ci} 29711cb0ef41Sopenharmony_ci 29721cb0ef41Sopenharmony_civoid Assembler::rint_s(FPURegister fd, FPURegister fs) { rint(S, fd, fs); } 29731cb0ef41Sopenharmony_ci 29741cb0ef41Sopenharmony_civoid Assembler::rint_d(FPURegister fd, FPURegister fs) { rint(D, fd, fs); } 29751cb0ef41Sopenharmony_ci 29761cb0ef41Sopenharmony_civoid Assembler::rint(SecondaryField fmt, FPURegister fd, FPURegister fs) { 29771cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 29781cb0ef41Sopenharmony_ci GenInstrRegister(COP1, fmt, f0, fs, fd, RINT); 29791cb0ef41Sopenharmony_ci} 29801cb0ef41Sopenharmony_ci 29811cb0ef41Sopenharmony_civoid Assembler::cvt_l_s(FPURegister fd, FPURegister fs) { 29821cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 29831cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S); 29841cb0ef41Sopenharmony_ci} 29851cb0ef41Sopenharmony_ci 29861cb0ef41Sopenharmony_civoid Assembler::cvt_l_d(FPURegister fd, FPURegister fs) { 29871cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 29881cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D); 29891cb0ef41Sopenharmony_ci} 29901cb0ef41Sopenharmony_ci 29911cb0ef41Sopenharmony_civoid Assembler::trunc_l_s(FPURegister fd, FPURegister fs) { 29921cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 29931cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S); 29941cb0ef41Sopenharmony_ci} 29951cb0ef41Sopenharmony_ci 29961cb0ef41Sopenharmony_civoid Assembler::trunc_l_d(FPURegister fd, FPURegister fs) { 29971cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 29981cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D); 29991cb0ef41Sopenharmony_ci} 30001cb0ef41Sopenharmony_ci 30011cb0ef41Sopenharmony_civoid Assembler::round_l_s(FPURegister fd, FPURegister fs) { 30021cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S); 30031cb0ef41Sopenharmony_ci} 30041cb0ef41Sopenharmony_ci 30051cb0ef41Sopenharmony_civoid Assembler::round_l_d(FPURegister fd, FPURegister fs) { 30061cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, ROUND_L_D); 30071cb0ef41Sopenharmony_ci} 30081cb0ef41Sopenharmony_ci 30091cb0ef41Sopenharmony_civoid Assembler::floor_l_s(FPURegister fd, FPURegister fs) { 30101cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, FLOOR_L_S); 30111cb0ef41Sopenharmony_ci} 30121cb0ef41Sopenharmony_ci 30131cb0ef41Sopenharmony_civoid Assembler::floor_l_d(FPURegister fd, FPURegister fs) { 30141cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, FLOOR_L_D); 30151cb0ef41Sopenharmony_ci} 30161cb0ef41Sopenharmony_ci 30171cb0ef41Sopenharmony_civoid Assembler::ceil_l_s(FPURegister fd, FPURegister fs) { 30181cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S); 30191cb0ef41Sopenharmony_ci} 30201cb0ef41Sopenharmony_ci 30211cb0ef41Sopenharmony_civoid Assembler::ceil_l_d(FPURegister fd, FPURegister fs) { 30221cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D); 30231cb0ef41Sopenharmony_ci} 30241cb0ef41Sopenharmony_ci 30251cb0ef41Sopenharmony_civoid Assembler::class_s(FPURegister fd, FPURegister fs) { 30261cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 30271cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, CLASS_S); 30281cb0ef41Sopenharmony_ci} 30291cb0ef41Sopenharmony_ci 30301cb0ef41Sopenharmony_civoid Assembler::class_d(FPURegister fd, FPURegister fs) { 30311cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 30321cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, CLASS_D); 30331cb0ef41Sopenharmony_ci} 30341cb0ef41Sopenharmony_ci 30351cb0ef41Sopenharmony_civoid Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister fs, 30361cb0ef41Sopenharmony_ci FPURegister ft) { 30371cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 30381cb0ef41Sopenharmony_ci DCHECK((fmt == D) || (fmt == S)); 30391cb0ef41Sopenharmony_ci GenInstrRegister(COP1, fmt, ft, fs, fd, MINA); 30401cb0ef41Sopenharmony_ci} 30411cb0ef41Sopenharmony_ci 30421cb0ef41Sopenharmony_civoid Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister fs, 30431cb0ef41Sopenharmony_ci FPURegister ft) { 30441cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 30451cb0ef41Sopenharmony_ci DCHECK((fmt == D) || (fmt == S)); 30461cb0ef41Sopenharmony_ci GenInstrRegister(COP1, fmt, ft, fs, fd, MAXA); 30471cb0ef41Sopenharmony_ci} 30481cb0ef41Sopenharmony_ci 30491cb0ef41Sopenharmony_civoid Assembler::cvt_s_w(FPURegister fd, FPURegister fs) { 30501cb0ef41Sopenharmony_ci GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W); 30511cb0ef41Sopenharmony_ci} 30521cb0ef41Sopenharmony_ci 30531cb0ef41Sopenharmony_civoid Assembler::cvt_s_l(FPURegister fd, FPURegister fs) { 30541cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 30551cb0ef41Sopenharmony_ci GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L); 30561cb0ef41Sopenharmony_ci} 30571cb0ef41Sopenharmony_ci 30581cb0ef41Sopenharmony_civoid Assembler::cvt_s_d(FPURegister fd, FPURegister fs) { 30591cb0ef41Sopenharmony_ci GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D); 30601cb0ef41Sopenharmony_ci} 30611cb0ef41Sopenharmony_ci 30621cb0ef41Sopenharmony_civoid Assembler::cvt_d_w(FPURegister fd, FPURegister fs) { 30631cb0ef41Sopenharmony_ci GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W); 30641cb0ef41Sopenharmony_ci} 30651cb0ef41Sopenharmony_ci 30661cb0ef41Sopenharmony_civoid Assembler::cvt_d_l(FPURegister fd, FPURegister fs) { 30671cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r2 || kArchVariant == kMips64r6); 30681cb0ef41Sopenharmony_ci GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L); 30691cb0ef41Sopenharmony_ci} 30701cb0ef41Sopenharmony_ci 30711cb0ef41Sopenharmony_civoid Assembler::cvt_d_s(FPURegister fd, FPURegister fs) { 30721cb0ef41Sopenharmony_ci GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S); 30731cb0ef41Sopenharmony_ci} 30741cb0ef41Sopenharmony_ci 30751cb0ef41Sopenharmony_ci// Conditions for >= MIPSr6. 30761cb0ef41Sopenharmony_civoid Assembler::cmp(FPUCondition cond, SecondaryField fmt, FPURegister fd, 30771cb0ef41Sopenharmony_ci FPURegister fs, FPURegister ft) { 30781cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 30791cb0ef41Sopenharmony_ci DCHECK_EQ(fmt & ~(31 << kRsShift), 0); 30801cb0ef41Sopenharmony_ci Instr instr = COP1 | fmt | ft.code() << kFtShift | fs.code() << kFsShift | 30811cb0ef41Sopenharmony_ci fd.code() << kFdShift | (0 << 5) | cond; 30821cb0ef41Sopenharmony_ci emit(instr); 30831cb0ef41Sopenharmony_ci} 30841cb0ef41Sopenharmony_ci 30851cb0ef41Sopenharmony_civoid Assembler::cmp_s(FPUCondition cond, FPURegister fd, FPURegister fs, 30861cb0ef41Sopenharmony_ci FPURegister ft) { 30871cb0ef41Sopenharmony_ci cmp(cond, W, fd, fs, ft); 30881cb0ef41Sopenharmony_ci} 30891cb0ef41Sopenharmony_ci 30901cb0ef41Sopenharmony_civoid Assembler::cmp_d(FPUCondition cond, FPURegister fd, FPURegister fs, 30911cb0ef41Sopenharmony_ci FPURegister ft) { 30921cb0ef41Sopenharmony_ci cmp(cond, L, fd, fs, ft); 30931cb0ef41Sopenharmony_ci} 30941cb0ef41Sopenharmony_ci 30951cb0ef41Sopenharmony_civoid Assembler::bc1eqz(int16_t offset, FPURegister ft) { 30961cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 30971cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 30981cb0ef41Sopenharmony_ci Instr instr = COP1 | BC1EQZ | ft.code() << kFtShift | (offset & kImm16Mask); 30991cb0ef41Sopenharmony_ci emit(instr); 31001cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 31011cb0ef41Sopenharmony_ci} 31021cb0ef41Sopenharmony_ci 31031cb0ef41Sopenharmony_civoid Assembler::bc1nez(int16_t offset, FPURegister ft) { 31041cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6); 31051cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 31061cb0ef41Sopenharmony_ci Instr instr = COP1 | BC1NEZ | ft.code() << kFtShift | (offset & kImm16Mask); 31071cb0ef41Sopenharmony_ci emit(instr); 31081cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 31091cb0ef41Sopenharmony_ci} 31101cb0ef41Sopenharmony_ci 31111cb0ef41Sopenharmony_ci// Conditions for < MIPSr6. 31121cb0ef41Sopenharmony_civoid Assembler::c(FPUCondition cond, SecondaryField fmt, FPURegister fs, 31131cb0ef41Sopenharmony_ci FPURegister ft, uint16_t cc) { 31141cb0ef41Sopenharmony_ci DCHECK_NE(kArchVariant, kMips64r6); 31151cb0ef41Sopenharmony_ci DCHECK(is_uint3(cc)); 31161cb0ef41Sopenharmony_ci DCHECK(fmt == S || fmt == D); 31171cb0ef41Sopenharmony_ci DCHECK_EQ(fmt & ~(31 << kRsShift), 0); 31181cb0ef41Sopenharmony_ci Instr instr = COP1 | fmt | ft.code() << kFtShift | fs.code() << kFsShift | 31191cb0ef41Sopenharmony_ci cc << 8 | 3 << 4 | cond; 31201cb0ef41Sopenharmony_ci emit(instr); 31211cb0ef41Sopenharmony_ci} 31221cb0ef41Sopenharmony_ci 31231cb0ef41Sopenharmony_civoid Assembler::c_s(FPUCondition cond, FPURegister fs, FPURegister ft, 31241cb0ef41Sopenharmony_ci uint16_t cc) { 31251cb0ef41Sopenharmony_ci c(cond, S, fs, ft, cc); 31261cb0ef41Sopenharmony_ci} 31271cb0ef41Sopenharmony_ci 31281cb0ef41Sopenharmony_civoid Assembler::c_d(FPUCondition cond, FPURegister fs, FPURegister ft, 31291cb0ef41Sopenharmony_ci uint16_t cc) { 31301cb0ef41Sopenharmony_ci c(cond, D, fs, ft, cc); 31311cb0ef41Sopenharmony_ci} 31321cb0ef41Sopenharmony_ci 31331cb0ef41Sopenharmony_civoid Assembler::fcmp(FPURegister src1, const double src2, FPUCondition cond) { 31341cb0ef41Sopenharmony_ci DCHECK_EQ(src2, 0.0); 31351cb0ef41Sopenharmony_ci mtc1(zero_reg, f14); 31361cb0ef41Sopenharmony_ci cvt_d_w(f14, f14); 31371cb0ef41Sopenharmony_ci c(cond, D, src1, f14, 0); 31381cb0ef41Sopenharmony_ci} 31391cb0ef41Sopenharmony_ci 31401cb0ef41Sopenharmony_civoid Assembler::bc1f(int16_t offset, uint16_t cc) { 31411cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 31421cb0ef41Sopenharmony_ci DCHECK(is_uint3(cc)); 31431cb0ef41Sopenharmony_ci Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask); 31441cb0ef41Sopenharmony_ci emit(instr); 31451cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 31461cb0ef41Sopenharmony_ci} 31471cb0ef41Sopenharmony_ci 31481cb0ef41Sopenharmony_civoid Assembler::bc1t(int16_t offset, uint16_t cc) { 31491cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 31501cb0ef41Sopenharmony_ci DCHECK(is_uint3(cc)); 31511cb0ef41Sopenharmony_ci Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask); 31521cb0ef41Sopenharmony_ci emit(instr); 31531cb0ef41Sopenharmony_ci BlockTrampolinePoolFor(1); // For associated delay slot. 31541cb0ef41Sopenharmony_ci} 31551cb0ef41Sopenharmony_ci 31561cb0ef41Sopenharmony_ci// ---------- MSA instructions ------------ 31571cb0ef41Sopenharmony_ci#define MSA_BRANCH_LIST(V) \ 31581cb0ef41Sopenharmony_ci V(bz_v, BZ_V) \ 31591cb0ef41Sopenharmony_ci V(bz_b, BZ_B) \ 31601cb0ef41Sopenharmony_ci V(bz_h, BZ_H) \ 31611cb0ef41Sopenharmony_ci V(bz_w, BZ_W) \ 31621cb0ef41Sopenharmony_ci V(bz_d, BZ_D) \ 31631cb0ef41Sopenharmony_ci V(bnz_v, BNZ_V) \ 31641cb0ef41Sopenharmony_ci V(bnz_b, BNZ_B) \ 31651cb0ef41Sopenharmony_ci V(bnz_h, BNZ_H) \ 31661cb0ef41Sopenharmony_ci V(bnz_w, BNZ_W) \ 31671cb0ef41Sopenharmony_ci V(bnz_d, BNZ_D) 31681cb0ef41Sopenharmony_ci 31691cb0ef41Sopenharmony_ci#define MSA_BRANCH(name, opcode) \ 31701cb0ef41Sopenharmony_ci void Assembler::name(MSARegister wt, int16_t offset) { \ 31711cb0ef41Sopenharmony_ci GenInstrMsaBranch(opcode, wt, offset); \ 31721cb0ef41Sopenharmony_ci } 31731cb0ef41Sopenharmony_ci 31741cb0ef41Sopenharmony_ciMSA_BRANCH_LIST(MSA_BRANCH) 31751cb0ef41Sopenharmony_ci#undef MSA_BRANCH 31761cb0ef41Sopenharmony_ci#undef MSA_BRANCH_LIST 31771cb0ef41Sopenharmony_ci 31781cb0ef41Sopenharmony_ci#define MSA_LD_ST_LIST(V) \ 31791cb0ef41Sopenharmony_ci V(ld_b, LD_B, 1) \ 31801cb0ef41Sopenharmony_ci V(ld_h, LD_H, 2) \ 31811cb0ef41Sopenharmony_ci V(ld_w, LD_W, 4) \ 31821cb0ef41Sopenharmony_ci V(ld_d, LD_D, 8) \ 31831cb0ef41Sopenharmony_ci V(st_b, ST_B, 1) \ 31841cb0ef41Sopenharmony_ci V(st_h, ST_H, 2) \ 31851cb0ef41Sopenharmony_ci V(st_w, ST_W, 4) \ 31861cb0ef41Sopenharmony_ci V(st_d, ST_D, 8) 31871cb0ef41Sopenharmony_ci 31881cb0ef41Sopenharmony_ci#define MSA_LD_ST(name, opcode, b) \ 31891cb0ef41Sopenharmony_ci void Assembler::name(MSARegister wd, const MemOperand& rs) { \ 31901cb0ef41Sopenharmony_ci MemOperand source = rs; \ 31911cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); \ 31921cb0ef41Sopenharmony_ci if (is_int10(source.offset())) { \ 31931cb0ef41Sopenharmony_ci DCHECK_EQ(source.offset() % b, 0); \ 31941cb0ef41Sopenharmony_ci GenInstrMsaMI10(opcode, source.offset() / b, source.rm(), wd); \ 31951cb0ef41Sopenharmony_ci } else { \ 31961cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); \ 31971cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); \ 31981cb0ef41Sopenharmony_ci DCHECK_NE(rs.rm(), scratch); \ 31991cb0ef41Sopenharmony_ci daddiu(scratch, source.rm(), source.offset()); \ 32001cb0ef41Sopenharmony_ci GenInstrMsaMI10(opcode, 0, scratch, wd); \ 32011cb0ef41Sopenharmony_ci } \ 32021cb0ef41Sopenharmony_ci } 32031cb0ef41Sopenharmony_ci 32041cb0ef41Sopenharmony_ciMSA_LD_ST_LIST(MSA_LD_ST) 32051cb0ef41Sopenharmony_ci#undef MSA_LD_ST 32061cb0ef41Sopenharmony_ci#undef MSA_LD_ST_LIST 32071cb0ef41Sopenharmony_ci 32081cb0ef41Sopenharmony_ci#define MSA_I10_LIST(V) \ 32091cb0ef41Sopenharmony_ci V(ldi_b, I5_DF_b) \ 32101cb0ef41Sopenharmony_ci V(ldi_h, I5_DF_h) \ 32111cb0ef41Sopenharmony_ci V(ldi_w, I5_DF_w) \ 32121cb0ef41Sopenharmony_ci V(ldi_d, I5_DF_d) 32131cb0ef41Sopenharmony_ci 32141cb0ef41Sopenharmony_ci#define MSA_I10(name, format) \ 32151cb0ef41Sopenharmony_ci void Assembler::name(MSARegister wd, int32_t imm10) { \ 32161cb0ef41Sopenharmony_ci GenInstrMsaI10(LDI, format, imm10, wd); \ 32171cb0ef41Sopenharmony_ci } 32181cb0ef41Sopenharmony_ciMSA_I10_LIST(MSA_I10) 32191cb0ef41Sopenharmony_ci#undef MSA_I10 32201cb0ef41Sopenharmony_ci#undef MSA_I10_LIST 32211cb0ef41Sopenharmony_ci 32221cb0ef41Sopenharmony_ci#define MSA_I5_LIST(V) \ 32231cb0ef41Sopenharmony_ci V(addvi, ADDVI) \ 32241cb0ef41Sopenharmony_ci V(subvi, SUBVI) \ 32251cb0ef41Sopenharmony_ci V(maxi_s, MAXI_S) \ 32261cb0ef41Sopenharmony_ci V(maxi_u, MAXI_U) \ 32271cb0ef41Sopenharmony_ci V(mini_s, MINI_S) \ 32281cb0ef41Sopenharmony_ci V(mini_u, MINI_U) \ 32291cb0ef41Sopenharmony_ci V(ceqi, CEQI) \ 32301cb0ef41Sopenharmony_ci V(clti_s, CLTI_S) \ 32311cb0ef41Sopenharmony_ci V(clti_u, CLTI_U) \ 32321cb0ef41Sopenharmony_ci V(clei_s, CLEI_S) \ 32331cb0ef41Sopenharmony_ci V(clei_u, CLEI_U) 32341cb0ef41Sopenharmony_ci 32351cb0ef41Sopenharmony_ci#define MSA_I5_FORMAT(name, opcode, format) \ 32361cb0ef41Sopenharmony_ci void Assembler::name##_##format(MSARegister wd, MSARegister ws, \ 32371cb0ef41Sopenharmony_ci uint32_t imm5) { \ 32381cb0ef41Sopenharmony_ci GenInstrMsaI5(opcode, I5_DF_##format, imm5, ws, wd); \ 32391cb0ef41Sopenharmony_ci } 32401cb0ef41Sopenharmony_ci 32411cb0ef41Sopenharmony_ci#define MSA_I5(name, opcode) \ 32421cb0ef41Sopenharmony_ci MSA_I5_FORMAT(name, opcode, b) \ 32431cb0ef41Sopenharmony_ci MSA_I5_FORMAT(name, opcode, h) \ 32441cb0ef41Sopenharmony_ci MSA_I5_FORMAT(name, opcode, w) \ 32451cb0ef41Sopenharmony_ci MSA_I5_FORMAT(name, opcode, d) 32461cb0ef41Sopenharmony_ci 32471cb0ef41Sopenharmony_ciMSA_I5_LIST(MSA_I5) 32481cb0ef41Sopenharmony_ci#undef MSA_I5 32491cb0ef41Sopenharmony_ci#undef MSA_I5_FORMAT 32501cb0ef41Sopenharmony_ci#undef MSA_I5_LIST 32511cb0ef41Sopenharmony_ci 32521cb0ef41Sopenharmony_ci#define MSA_I8_LIST(V) \ 32531cb0ef41Sopenharmony_ci V(andi_b, ANDI_B) \ 32541cb0ef41Sopenharmony_ci V(ori_b, ORI_B) \ 32551cb0ef41Sopenharmony_ci V(nori_b, NORI_B) \ 32561cb0ef41Sopenharmony_ci V(xori_b, XORI_B) \ 32571cb0ef41Sopenharmony_ci V(bmnzi_b, BMNZI_B) \ 32581cb0ef41Sopenharmony_ci V(bmzi_b, BMZI_B) \ 32591cb0ef41Sopenharmony_ci V(bseli_b, BSELI_B) \ 32601cb0ef41Sopenharmony_ci V(shf_b, SHF_B) \ 32611cb0ef41Sopenharmony_ci V(shf_h, SHF_H) \ 32621cb0ef41Sopenharmony_ci V(shf_w, SHF_W) 32631cb0ef41Sopenharmony_ci 32641cb0ef41Sopenharmony_ci#define MSA_I8(name, opcode) \ 32651cb0ef41Sopenharmony_ci void Assembler::name(MSARegister wd, MSARegister ws, uint32_t imm8) { \ 32661cb0ef41Sopenharmony_ci GenInstrMsaI8(opcode, imm8, ws, wd); \ 32671cb0ef41Sopenharmony_ci } 32681cb0ef41Sopenharmony_ci 32691cb0ef41Sopenharmony_ciMSA_I8_LIST(MSA_I8) 32701cb0ef41Sopenharmony_ci#undef MSA_I8 32711cb0ef41Sopenharmony_ci#undef MSA_I8_LIST 32721cb0ef41Sopenharmony_ci 32731cb0ef41Sopenharmony_ci#define MSA_VEC_LIST(V) \ 32741cb0ef41Sopenharmony_ci V(and_v, AND_V) \ 32751cb0ef41Sopenharmony_ci V(or_v, OR_V) \ 32761cb0ef41Sopenharmony_ci V(nor_v, NOR_V) \ 32771cb0ef41Sopenharmony_ci V(xor_v, XOR_V) \ 32781cb0ef41Sopenharmony_ci V(bmnz_v, BMNZ_V) \ 32791cb0ef41Sopenharmony_ci V(bmz_v, BMZ_V) \ 32801cb0ef41Sopenharmony_ci V(bsel_v, BSEL_V) 32811cb0ef41Sopenharmony_ci 32821cb0ef41Sopenharmony_ci#define MSA_VEC(name, opcode) \ 32831cb0ef41Sopenharmony_ci void Assembler::name(MSARegister wd, MSARegister ws, MSARegister wt) { \ 32841cb0ef41Sopenharmony_ci GenInstrMsaVec(opcode, wt, ws, wd); \ 32851cb0ef41Sopenharmony_ci } 32861cb0ef41Sopenharmony_ci 32871cb0ef41Sopenharmony_ciMSA_VEC_LIST(MSA_VEC) 32881cb0ef41Sopenharmony_ci#undef MSA_VEC 32891cb0ef41Sopenharmony_ci#undef MSA_VEC_LIST 32901cb0ef41Sopenharmony_ci 32911cb0ef41Sopenharmony_ci#define MSA_2R_LIST(V) \ 32921cb0ef41Sopenharmony_ci V(pcnt, PCNT) \ 32931cb0ef41Sopenharmony_ci V(nloc, NLOC) \ 32941cb0ef41Sopenharmony_ci V(nlzc, NLZC) 32951cb0ef41Sopenharmony_ci 32961cb0ef41Sopenharmony_ci#define MSA_2R_FORMAT(name, opcode, format) \ 32971cb0ef41Sopenharmony_ci void Assembler::name##_##format(MSARegister wd, MSARegister ws) { \ 32981cb0ef41Sopenharmony_ci GenInstrMsa2R(opcode, MSA_2R_DF_##format, ws, wd); \ 32991cb0ef41Sopenharmony_ci } 33001cb0ef41Sopenharmony_ci 33011cb0ef41Sopenharmony_ci#define MSA_2R(name, opcode) \ 33021cb0ef41Sopenharmony_ci MSA_2R_FORMAT(name, opcode, b) \ 33031cb0ef41Sopenharmony_ci MSA_2R_FORMAT(name, opcode, h) \ 33041cb0ef41Sopenharmony_ci MSA_2R_FORMAT(name, opcode, w) \ 33051cb0ef41Sopenharmony_ci MSA_2R_FORMAT(name, opcode, d) 33061cb0ef41Sopenharmony_ci 33071cb0ef41Sopenharmony_ciMSA_2R_LIST(MSA_2R) 33081cb0ef41Sopenharmony_ci#undef MSA_2R 33091cb0ef41Sopenharmony_ci#undef MSA_2R_FORMAT 33101cb0ef41Sopenharmony_ci#undef MSA_2R_LIST 33111cb0ef41Sopenharmony_ci 33121cb0ef41Sopenharmony_ci#define MSA_FILL(format) \ 33131cb0ef41Sopenharmony_ci void Assembler::fill_##format(MSARegister wd, Register rs) { \ 33141cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); \ 33151cb0ef41Sopenharmony_ci DCHECK(rs.is_valid() && wd.is_valid()); \ 33161cb0ef41Sopenharmony_ci Instr instr = MSA | MSA_2R_FORMAT | FILL | MSA_2R_DF_##format | \ 33171cb0ef41Sopenharmony_ci (rs.code() << kWsShift) | (wd.code() << kWdShift) | \ 33181cb0ef41Sopenharmony_ci MSA_VEC_2R_2RF_MINOR; \ 33191cb0ef41Sopenharmony_ci emit(instr); \ 33201cb0ef41Sopenharmony_ci } 33211cb0ef41Sopenharmony_ci 33221cb0ef41Sopenharmony_ciMSA_FILL(b) 33231cb0ef41Sopenharmony_ciMSA_FILL(h) 33241cb0ef41Sopenharmony_ciMSA_FILL(w) 33251cb0ef41Sopenharmony_ciMSA_FILL(d) 33261cb0ef41Sopenharmony_ci#undef MSA_FILL 33271cb0ef41Sopenharmony_ci 33281cb0ef41Sopenharmony_ci#define MSA_2RF_LIST(V) \ 33291cb0ef41Sopenharmony_ci V(fclass, FCLASS) \ 33301cb0ef41Sopenharmony_ci V(ftrunc_s, FTRUNC_S) \ 33311cb0ef41Sopenharmony_ci V(ftrunc_u, FTRUNC_U) \ 33321cb0ef41Sopenharmony_ci V(fsqrt, FSQRT) \ 33331cb0ef41Sopenharmony_ci V(frsqrt, FRSQRT) \ 33341cb0ef41Sopenharmony_ci V(frcp, FRCP) \ 33351cb0ef41Sopenharmony_ci V(frint, FRINT) \ 33361cb0ef41Sopenharmony_ci V(flog2, FLOG2) \ 33371cb0ef41Sopenharmony_ci V(fexupl, FEXUPL) \ 33381cb0ef41Sopenharmony_ci V(fexupr, FEXUPR) \ 33391cb0ef41Sopenharmony_ci V(ffql, FFQL) \ 33401cb0ef41Sopenharmony_ci V(ffqr, FFQR) \ 33411cb0ef41Sopenharmony_ci V(ftint_s, FTINT_S) \ 33421cb0ef41Sopenharmony_ci V(ftint_u, FTINT_U) \ 33431cb0ef41Sopenharmony_ci V(ffint_s, FFINT_S) \ 33441cb0ef41Sopenharmony_ci V(ffint_u, FFINT_U) 33451cb0ef41Sopenharmony_ci 33461cb0ef41Sopenharmony_ci#define MSA_2RF_FORMAT(name, opcode, format) \ 33471cb0ef41Sopenharmony_ci void Assembler::name##_##format(MSARegister wd, MSARegister ws) { \ 33481cb0ef41Sopenharmony_ci GenInstrMsa2RF(opcode, MSA_2RF_DF_##format, ws, wd); \ 33491cb0ef41Sopenharmony_ci } 33501cb0ef41Sopenharmony_ci 33511cb0ef41Sopenharmony_ci#define MSA_2RF(name, opcode) \ 33521cb0ef41Sopenharmony_ci MSA_2RF_FORMAT(name, opcode, w) \ 33531cb0ef41Sopenharmony_ci MSA_2RF_FORMAT(name, opcode, d) 33541cb0ef41Sopenharmony_ci 33551cb0ef41Sopenharmony_ciMSA_2RF_LIST(MSA_2RF) 33561cb0ef41Sopenharmony_ci#undef MSA_2RF 33571cb0ef41Sopenharmony_ci#undef MSA_2RF_FORMAT 33581cb0ef41Sopenharmony_ci#undef MSA_2RF_LIST 33591cb0ef41Sopenharmony_ci 33601cb0ef41Sopenharmony_ci#define MSA_3R_LIST(V) \ 33611cb0ef41Sopenharmony_ci V(sll, SLL_MSA) \ 33621cb0ef41Sopenharmony_ci V(sra, SRA_MSA) \ 33631cb0ef41Sopenharmony_ci V(srl, SRL_MSA) \ 33641cb0ef41Sopenharmony_ci V(bclr, BCLR) \ 33651cb0ef41Sopenharmony_ci V(bset, BSET) \ 33661cb0ef41Sopenharmony_ci V(bneg, BNEG) \ 33671cb0ef41Sopenharmony_ci V(binsl, BINSL) \ 33681cb0ef41Sopenharmony_ci V(binsr, BINSR) \ 33691cb0ef41Sopenharmony_ci V(addv, ADDV) \ 33701cb0ef41Sopenharmony_ci V(subv, SUBV) \ 33711cb0ef41Sopenharmony_ci V(max_s, MAX_S) \ 33721cb0ef41Sopenharmony_ci V(max_u, MAX_U) \ 33731cb0ef41Sopenharmony_ci V(min_s, MIN_S) \ 33741cb0ef41Sopenharmony_ci V(min_u, MIN_U) \ 33751cb0ef41Sopenharmony_ci V(max_a, MAX_A) \ 33761cb0ef41Sopenharmony_ci V(min_a, MIN_A) \ 33771cb0ef41Sopenharmony_ci V(ceq, CEQ) \ 33781cb0ef41Sopenharmony_ci V(clt_s, CLT_S) \ 33791cb0ef41Sopenharmony_ci V(clt_u, CLT_U) \ 33801cb0ef41Sopenharmony_ci V(cle_s, CLE_S) \ 33811cb0ef41Sopenharmony_ci V(cle_u, CLE_U) \ 33821cb0ef41Sopenharmony_ci V(add_a, ADD_A) \ 33831cb0ef41Sopenharmony_ci V(adds_a, ADDS_A) \ 33841cb0ef41Sopenharmony_ci V(adds_s, ADDS_S) \ 33851cb0ef41Sopenharmony_ci V(adds_u, ADDS_U) \ 33861cb0ef41Sopenharmony_ci V(ave_s, AVE_S) \ 33871cb0ef41Sopenharmony_ci V(ave_u, AVE_U) \ 33881cb0ef41Sopenharmony_ci V(aver_s, AVER_S) \ 33891cb0ef41Sopenharmony_ci V(aver_u, AVER_U) \ 33901cb0ef41Sopenharmony_ci V(subs_s, SUBS_S) \ 33911cb0ef41Sopenharmony_ci V(subs_u, SUBS_U) \ 33921cb0ef41Sopenharmony_ci V(subsus_u, SUBSUS_U) \ 33931cb0ef41Sopenharmony_ci V(subsuu_s, SUBSUU_S) \ 33941cb0ef41Sopenharmony_ci V(asub_s, ASUB_S) \ 33951cb0ef41Sopenharmony_ci V(asub_u, ASUB_U) \ 33961cb0ef41Sopenharmony_ci V(mulv, MULV) \ 33971cb0ef41Sopenharmony_ci V(maddv, MADDV) \ 33981cb0ef41Sopenharmony_ci V(msubv, MSUBV) \ 33991cb0ef41Sopenharmony_ci V(div_s, DIV_S_MSA) \ 34001cb0ef41Sopenharmony_ci V(div_u, DIV_U) \ 34011cb0ef41Sopenharmony_ci V(mod_s, MOD_S) \ 34021cb0ef41Sopenharmony_ci V(mod_u, MOD_U) \ 34031cb0ef41Sopenharmony_ci V(dotp_s, DOTP_S) \ 34041cb0ef41Sopenharmony_ci V(dotp_u, DOTP_U) \ 34051cb0ef41Sopenharmony_ci V(dpadd_s, DPADD_S) \ 34061cb0ef41Sopenharmony_ci V(dpadd_u, DPADD_U) \ 34071cb0ef41Sopenharmony_ci V(dpsub_s, DPSUB_S) \ 34081cb0ef41Sopenharmony_ci V(dpsub_u, DPSUB_U) \ 34091cb0ef41Sopenharmony_ci V(pckev, PCKEV) \ 34101cb0ef41Sopenharmony_ci V(pckod, PCKOD) \ 34111cb0ef41Sopenharmony_ci V(ilvl, ILVL) \ 34121cb0ef41Sopenharmony_ci V(ilvr, ILVR) \ 34131cb0ef41Sopenharmony_ci V(ilvev, ILVEV) \ 34141cb0ef41Sopenharmony_ci V(ilvod, ILVOD) \ 34151cb0ef41Sopenharmony_ci V(vshf, VSHF) \ 34161cb0ef41Sopenharmony_ci V(srar, SRAR) \ 34171cb0ef41Sopenharmony_ci V(srlr, SRLR) \ 34181cb0ef41Sopenharmony_ci V(hadd_s, HADD_S) \ 34191cb0ef41Sopenharmony_ci V(hadd_u, HADD_U) \ 34201cb0ef41Sopenharmony_ci V(hsub_s, HSUB_S) \ 34211cb0ef41Sopenharmony_ci V(hsub_u, HSUB_U) 34221cb0ef41Sopenharmony_ci 34231cb0ef41Sopenharmony_ci#define MSA_3R_FORMAT(name, opcode, format) \ 34241cb0ef41Sopenharmony_ci void Assembler::name##_##format(MSARegister wd, MSARegister ws, \ 34251cb0ef41Sopenharmony_ci MSARegister wt) { \ 34261cb0ef41Sopenharmony_ci GenInstrMsa3R<MSARegister>(opcode, MSA_3R_DF_##format, wt, ws, wd); \ 34271cb0ef41Sopenharmony_ci } 34281cb0ef41Sopenharmony_ci 34291cb0ef41Sopenharmony_ci#define MSA_3R_FORMAT_SLD_SPLAT(name, opcode, format) \ 34301cb0ef41Sopenharmony_ci void Assembler::name##_##format(MSARegister wd, MSARegister ws, \ 34311cb0ef41Sopenharmony_ci Register rt) { \ 34321cb0ef41Sopenharmony_ci GenInstrMsa3R<Register>(opcode, MSA_3R_DF_##format, rt, ws, wd); \ 34331cb0ef41Sopenharmony_ci } 34341cb0ef41Sopenharmony_ci 34351cb0ef41Sopenharmony_ci#define MSA_3R(name, opcode) \ 34361cb0ef41Sopenharmony_ci MSA_3R_FORMAT(name, opcode, b) \ 34371cb0ef41Sopenharmony_ci MSA_3R_FORMAT(name, opcode, h) \ 34381cb0ef41Sopenharmony_ci MSA_3R_FORMAT(name, opcode, w) \ 34391cb0ef41Sopenharmony_ci MSA_3R_FORMAT(name, opcode, d) 34401cb0ef41Sopenharmony_ci 34411cb0ef41Sopenharmony_ci#define MSA_3R_SLD_SPLAT(name, opcode) \ 34421cb0ef41Sopenharmony_ci MSA_3R_FORMAT_SLD_SPLAT(name, opcode, b) \ 34431cb0ef41Sopenharmony_ci MSA_3R_FORMAT_SLD_SPLAT(name, opcode, h) \ 34441cb0ef41Sopenharmony_ci MSA_3R_FORMAT_SLD_SPLAT(name, opcode, w) \ 34451cb0ef41Sopenharmony_ci MSA_3R_FORMAT_SLD_SPLAT(name, opcode, d) 34461cb0ef41Sopenharmony_ci 34471cb0ef41Sopenharmony_ciMSA_3R_LIST(MSA_3R) 34481cb0ef41Sopenharmony_ciMSA_3R_SLD_SPLAT(sld, SLD) 34491cb0ef41Sopenharmony_ciMSA_3R_SLD_SPLAT(splat, SPLAT) 34501cb0ef41Sopenharmony_ci 34511cb0ef41Sopenharmony_ci#undef MSA_3R 34521cb0ef41Sopenharmony_ci#undef MSA_3R_FORMAT 34531cb0ef41Sopenharmony_ci#undef MSA_3R_FORMAT_SLD_SPLAT 34541cb0ef41Sopenharmony_ci#undef MSA_3R_SLD_SPLAT 34551cb0ef41Sopenharmony_ci#undef MSA_3R_LIST 34561cb0ef41Sopenharmony_ci 34571cb0ef41Sopenharmony_ci#define MSA_3RF_LIST1(V) \ 34581cb0ef41Sopenharmony_ci V(fcaf, FCAF) \ 34591cb0ef41Sopenharmony_ci V(fcun, FCUN) \ 34601cb0ef41Sopenharmony_ci V(fceq, FCEQ) \ 34611cb0ef41Sopenharmony_ci V(fcueq, FCUEQ) \ 34621cb0ef41Sopenharmony_ci V(fclt, FCLT) \ 34631cb0ef41Sopenharmony_ci V(fcult, FCULT) \ 34641cb0ef41Sopenharmony_ci V(fcle, FCLE) \ 34651cb0ef41Sopenharmony_ci V(fcule, FCULE) \ 34661cb0ef41Sopenharmony_ci V(fsaf, FSAF) \ 34671cb0ef41Sopenharmony_ci V(fsun, FSUN) \ 34681cb0ef41Sopenharmony_ci V(fseq, FSEQ) \ 34691cb0ef41Sopenharmony_ci V(fsueq, FSUEQ) \ 34701cb0ef41Sopenharmony_ci V(fslt, FSLT) \ 34711cb0ef41Sopenharmony_ci V(fsult, FSULT) \ 34721cb0ef41Sopenharmony_ci V(fsle, FSLE) \ 34731cb0ef41Sopenharmony_ci V(fsule, FSULE) \ 34741cb0ef41Sopenharmony_ci V(fadd, FADD) \ 34751cb0ef41Sopenharmony_ci V(fsub, FSUB) \ 34761cb0ef41Sopenharmony_ci V(fmul, FMUL) \ 34771cb0ef41Sopenharmony_ci V(fdiv, FDIV) \ 34781cb0ef41Sopenharmony_ci V(fmadd, FMADD) \ 34791cb0ef41Sopenharmony_ci V(fmsub, FMSUB) \ 34801cb0ef41Sopenharmony_ci V(fexp2, FEXP2) \ 34811cb0ef41Sopenharmony_ci V(fmin, FMIN) \ 34821cb0ef41Sopenharmony_ci V(fmin_a, FMIN_A) \ 34831cb0ef41Sopenharmony_ci V(fmax, FMAX) \ 34841cb0ef41Sopenharmony_ci V(fmax_a, FMAX_A) \ 34851cb0ef41Sopenharmony_ci V(fcor, FCOR) \ 34861cb0ef41Sopenharmony_ci V(fcune, FCUNE) \ 34871cb0ef41Sopenharmony_ci V(fcne, FCNE) \ 34881cb0ef41Sopenharmony_ci V(fsor, FSOR) \ 34891cb0ef41Sopenharmony_ci V(fsune, FSUNE) \ 34901cb0ef41Sopenharmony_ci V(fsne, FSNE) 34911cb0ef41Sopenharmony_ci 34921cb0ef41Sopenharmony_ci#define MSA_3RF_LIST2(V) \ 34931cb0ef41Sopenharmony_ci V(fexdo, FEXDO) \ 34941cb0ef41Sopenharmony_ci V(ftq, FTQ) \ 34951cb0ef41Sopenharmony_ci V(mul_q, MUL_Q) \ 34961cb0ef41Sopenharmony_ci V(madd_q, MADD_Q) \ 34971cb0ef41Sopenharmony_ci V(msub_q, MSUB_Q) \ 34981cb0ef41Sopenharmony_ci V(mulr_q, MULR_Q) \ 34991cb0ef41Sopenharmony_ci V(maddr_q, MADDR_Q) \ 35001cb0ef41Sopenharmony_ci V(msubr_q, MSUBR_Q) 35011cb0ef41Sopenharmony_ci 35021cb0ef41Sopenharmony_ci#define MSA_3RF_FORMAT(name, opcode, df, df_c) \ 35031cb0ef41Sopenharmony_ci void Assembler::name##_##df(MSARegister wd, MSARegister ws, \ 35041cb0ef41Sopenharmony_ci MSARegister wt) { \ 35051cb0ef41Sopenharmony_ci GenInstrMsa3RF(opcode, df_c, wt, ws, wd); \ 35061cb0ef41Sopenharmony_ci } 35071cb0ef41Sopenharmony_ci 35081cb0ef41Sopenharmony_ci#define MSA_3RF_1(name, opcode) \ 35091cb0ef41Sopenharmony_ci MSA_3RF_FORMAT(name, opcode, w, 0) \ 35101cb0ef41Sopenharmony_ci MSA_3RF_FORMAT(name, opcode, d, 1) 35111cb0ef41Sopenharmony_ci 35121cb0ef41Sopenharmony_ci#define MSA_3RF_2(name, opcode) \ 35131cb0ef41Sopenharmony_ci MSA_3RF_FORMAT(name, opcode, h, 0) \ 35141cb0ef41Sopenharmony_ci MSA_3RF_FORMAT(name, opcode, w, 1) 35151cb0ef41Sopenharmony_ci 35161cb0ef41Sopenharmony_ciMSA_3RF_LIST1(MSA_3RF_1) 35171cb0ef41Sopenharmony_ciMSA_3RF_LIST2(MSA_3RF_2) 35181cb0ef41Sopenharmony_ci#undef MSA_3RF_1 35191cb0ef41Sopenharmony_ci#undef MSA_3RF_2 35201cb0ef41Sopenharmony_ci#undef MSA_3RF_FORMAT 35211cb0ef41Sopenharmony_ci#undef MSA_3RF_LIST1 35221cb0ef41Sopenharmony_ci#undef MSA_3RF_LIST2 35231cb0ef41Sopenharmony_ci 35241cb0ef41Sopenharmony_civoid Assembler::sldi_b(MSARegister wd, MSARegister ws, uint32_t n) { 35251cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_B, n, ws, wd); 35261cb0ef41Sopenharmony_ci} 35271cb0ef41Sopenharmony_ci 35281cb0ef41Sopenharmony_civoid Assembler::sldi_h(MSARegister wd, MSARegister ws, uint32_t n) { 35291cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_H, n, ws, wd); 35301cb0ef41Sopenharmony_ci} 35311cb0ef41Sopenharmony_ci 35321cb0ef41Sopenharmony_civoid Assembler::sldi_w(MSARegister wd, MSARegister ws, uint32_t n) { 35331cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_W, n, ws, wd); 35341cb0ef41Sopenharmony_ci} 35351cb0ef41Sopenharmony_ci 35361cb0ef41Sopenharmony_civoid Assembler::sldi_d(MSARegister wd, MSARegister ws, uint32_t n) { 35371cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(SLDI, ELM_DF_D, n, ws, wd); 35381cb0ef41Sopenharmony_ci} 35391cb0ef41Sopenharmony_ci 35401cb0ef41Sopenharmony_civoid Assembler::splati_b(MSARegister wd, MSARegister ws, uint32_t n) { 35411cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_B, n, ws, wd); 35421cb0ef41Sopenharmony_ci} 35431cb0ef41Sopenharmony_ci 35441cb0ef41Sopenharmony_civoid Assembler::splati_h(MSARegister wd, MSARegister ws, uint32_t n) { 35451cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_H, n, ws, wd); 35461cb0ef41Sopenharmony_ci} 35471cb0ef41Sopenharmony_ci 35481cb0ef41Sopenharmony_civoid Assembler::splati_w(MSARegister wd, MSARegister ws, uint32_t n) { 35491cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_W, n, ws, wd); 35501cb0ef41Sopenharmony_ci} 35511cb0ef41Sopenharmony_ci 35521cb0ef41Sopenharmony_civoid Assembler::splati_d(MSARegister wd, MSARegister ws, uint32_t n) { 35531cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(SPLATI, ELM_DF_D, n, ws, wd); 35541cb0ef41Sopenharmony_ci} 35551cb0ef41Sopenharmony_ci 35561cb0ef41Sopenharmony_civoid Assembler::copy_s_b(Register rd, MSARegister ws, uint32_t n) { 35571cb0ef41Sopenharmony_ci GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_B, n, ws, rd); 35581cb0ef41Sopenharmony_ci} 35591cb0ef41Sopenharmony_ci 35601cb0ef41Sopenharmony_civoid Assembler::copy_s_h(Register rd, MSARegister ws, uint32_t n) { 35611cb0ef41Sopenharmony_ci GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_H, n, ws, rd); 35621cb0ef41Sopenharmony_ci} 35631cb0ef41Sopenharmony_ci 35641cb0ef41Sopenharmony_civoid Assembler::copy_s_w(Register rd, MSARegister ws, uint32_t n) { 35651cb0ef41Sopenharmony_ci GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_W, n, ws, rd); 35661cb0ef41Sopenharmony_ci} 35671cb0ef41Sopenharmony_ci 35681cb0ef41Sopenharmony_civoid Assembler::copy_s_d(Register rd, MSARegister ws, uint32_t n) { 35691cb0ef41Sopenharmony_ci GenInstrMsaElm<Register, MSARegister>(COPY_S, ELM_DF_D, n, ws, rd); 35701cb0ef41Sopenharmony_ci} 35711cb0ef41Sopenharmony_ci 35721cb0ef41Sopenharmony_civoid Assembler::copy_u_b(Register rd, MSARegister ws, uint32_t n) { 35731cb0ef41Sopenharmony_ci GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_B, n, ws, rd); 35741cb0ef41Sopenharmony_ci} 35751cb0ef41Sopenharmony_ci 35761cb0ef41Sopenharmony_civoid Assembler::copy_u_h(Register rd, MSARegister ws, uint32_t n) { 35771cb0ef41Sopenharmony_ci GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_H, n, ws, rd); 35781cb0ef41Sopenharmony_ci} 35791cb0ef41Sopenharmony_ci 35801cb0ef41Sopenharmony_civoid Assembler::copy_u_w(Register rd, MSARegister ws, uint32_t n) { 35811cb0ef41Sopenharmony_ci GenInstrMsaElm<Register, MSARegister>(COPY_U, ELM_DF_W, n, ws, rd); 35821cb0ef41Sopenharmony_ci} 35831cb0ef41Sopenharmony_ci 35841cb0ef41Sopenharmony_civoid Assembler::insert_b(MSARegister wd, uint32_t n, Register rs) { 35851cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_B, n, rs, wd); 35861cb0ef41Sopenharmony_ci} 35871cb0ef41Sopenharmony_ci 35881cb0ef41Sopenharmony_civoid Assembler::insert_h(MSARegister wd, uint32_t n, Register rs) { 35891cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_H, n, rs, wd); 35901cb0ef41Sopenharmony_ci} 35911cb0ef41Sopenharmony_ci 35921cb0ef41Sopenharmony_civoid Assembler::insert_w(MSARegister wd, uint32_t n, Register rs) { 35931cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_W, n, rs, wd); 35941cb0ef41Sopenharmony_ci} 35951cb0ef41Sopenharmony_ci 35961cb0ef41Sopenharmony_civoid Assembler::insert_d(MSARegister wd, uint32_t n, Register rs) { 35971cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, Register>(INSERT, ELM_DF_D, n, rs, wd); 35981cb0ef41Sopenharmony_ci} 35991cb0ef41Sopenharmony_ci 36001cb0ef41Sopenharmony_civoid Assembler::insve_b(MSARegister wd, uint32_t n, MSARegister ws) { 36011cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_B, n, ws, wd); 36021cb0ef41Sopenharmony_ci} 36031cb0ef41Sopenharmony_ci 36041cb0ef41Sopenharmony_civoid Assembler::insve_h(MSARegister wd, uint32_t n, MSARegister ws) { 36051cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_H, n, ws, wd); 36061cb0ef41Sopenharmony_ci} 36071cb0ef41Sopenharmony_ci 36081cb0ef41Sopenharmony_civoid Assembler::insve_w(MSARegister wd, uint32_t n, MSARegister ws) { 36091cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_W, n, ws, wd); 36101cb0ef41Sopenharmony_ci} 36111cb0ef41Sopenharmony_ci 36121cb0ef41Sopenharmony_civoid Assembler::insve_d(MSARegister wd, uint32_t n, MSARegister ws) { 36131cb0ef41Sopenharmony_ci GenInstrMsaElm<MSARegister, MSARegister>(INSVE, ELM_DF_D, n, ws, wd); 36141cb0ef41Sopenharmony_ci} 36151cb0ef41Sopenharmony_ci 36161cb0ef41Sopenharmony_civoid Assembler::move_v(MSARegister wd, MSARegister ws) { 36171cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 36181cb0ef41Sopenharmony_ci DCHECK(ws.is_valid() && wd.is_valid()); 36191cb0ef41Sopenharmony_ci Instr instr = MSA | MOVE_V | (ws.code() << kWsShift) | 36201cb0ef41Sopenharmony_ci (wd.code() << kWdShift) | MSA_ELM_MINOR; 36211cb0ef41Sopenharmony_ci emit(instr); 36221cb0ef41Sopenharmony_ci} 36231cb0ef41Sopenharmony_ci 36241cb0ef41Sopenharmony_civoid Assembler::ctcmsa(MSAControlRegister cd, Register rs) { 36251cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 36261cb0ef41Sopenharmony_ci DCHECK(cd.is_valid() && rs.is_valid()); 36271cb0ef41Sopenharmony_ci Instr instr = MSA | CTCMSA | (rs.code() << kWsShift) | 36281cb0ef41Sopenharmony_ci (cd.code() << kWdShift) | MSA_ELM_MINOR; 36291cb0ef41Sopenharmony_ci emit(instr); 36301cb0ef41Sopenharmony_ci} 36311cb0ef41Sopenharmony_ci 36321cb0ef41Sopenharmony_civoid Assembler::cfcmsa(Register rd, MSAControlRegister cs) { 36331cb0ef41Sopenharmony_ci DCHECK(IsEnabled(MIPS_SIMD)); 36341cb0ef41Sopenharmony_ci DCHECK(rd.is_valid() && cs.is_valid()); 36351cb0ef41Sopenharmony_ci Instr instr = MSA | CFCMSA | (cs.code() << kWsShift) | 36361cb0ef41Sopenharmony_ci (rd.code() << kWdShift) | MSA_ELM_MINOR; 36371cb0ef41Sopenharmony_ci emit(instr); 36381cb0ef41Sopenharmony_ci} 36391cb0ef41Sopenharmony_ci 36401cb0ef41Sopenharmony_ci#define MSA_BIT_LIST(V) \ 36411cb0ef41Sopenharmony_ci V(slli, SLLI) \ 36421cb0ef41Sopenharmony_ci V(srai, SRAI) \ 36431cb0ef41Sopenharmony_ci V(srli, SRLI) \ 36441cb0ef41Sopenharmony_ci V(bclri, BCLRI) \ 36451cb0ef41Sopenharmony_ci V(bseti, BSETI) \ 36461cb0ef41Sopenharmony_ci V(bnegi, BNEGI) \ 36471cb0ef41Sopenharmony_ci V(binsli, BINSLI) \ 36481cb0ef41Sopenharmony_ci V(binsri, BINSRI) \ 36491cb0ef41Sopenharmony_ci V(sat_s, SAT_S) \ 36501cb0ef41Sopenharmony_ci V(sat_u, SAT_U) \ 36511cb0ef41Sopenharmony_ci V(srari, SRARI) \ 36521cb0ef41Sopenharmony_ci V(srlri, SRLRI) 36531cb0ef41Sopenharmony_ci 36541cb0ef41Sopenharmony_ci#define MSA_BIT_FORMAT(name, opcode, format) \ 36551cb0ef41Sopenharmony_ci void Assembler::name##_##format(MSARegister wd, MSARegister ws, \ 36561cb0ef41Sopenharmony_ci uint32_t m) { \ 36571cb0ef41Sopenharmony_ci GenInstrMsaBit(opcode, BIT_DF_##format, m, ws, wd); \ 36581cb0ef41Sopenharmony_ci } 36591cb0ef41Sopenharmony_ci 36601cb0ef41Sopenharmony_ci#define MSA_BIT(name, opcode) \ 36611cb0ef41Sopenharmony_ci MSA_BIT_FORMAT(name, opcode, b) \ 36621cb0ef41Sopenharmony_ci MSA_BIT_FORMAT(name, opcode, h) \ 36631cb0ef41Sopenharmony_ci MSA_BIT_FORMAT(name, opcode, w) \ 36641cb0ef41Sopenharmony_ci MSA_BIT_FORMAT(name, opcode, d) 36651cb0ef41Sopenharmony_ci 36661cb0ef41Sopenharmony_ciMSA_BIT_LIST(MSA_BIT) 36671cb0ef41Sopenharmony_ci#undef MSA_BIT 36681cb0ef41Sopenharmony_ci#undef MSA_BIT_FORMAT 36691cb0ef41Sopenharmony_ci#undef MSA_BIT_LIST 36701cb0ef41Sopenharmony_ci 36711cb0ef41Sopenharmony_ciint Assembler::RelocateInternalReference(RelocInfo::Mode rmode, Address pc, 36721cb0ef41Sopenharmony_ci intptr_t pc_delta) { 36731cb0ef41Sopenharmony_ci if (RelocInfo::IsInternalReference(rmode)) { 36741cb0ef41Sopenharmony_ci int64_t* p = reinterpret_cast<int64_t*>(pc); 36751cb0ef41Sopenharmony_ci if (*p == kEndOfJumpChain) { 36761cb0ef41Sopenharmony_ci return 0; // Number of instructions patched. 36771cb0ef41Sopenharmony_ci } 36781cb0ef41Sopenharmony_ci *p += pc_delta; 36791cb0ef41Sopenharmony_ci return 2; // Number of instructions patched. 36801cb0ef41Sopenharmony_ci } 36811cb0ef41Sopenharmony_ci Instr instr = instr_at(pc); 36821cb0ef41Sopenharmony_ci DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode)); 36831cb0ef41Sopenharmony_ci if (IsLui(instr)) { 36841cb0ef41Sopenharmony_ci Instr instr_lui = instr_at(pc + 0 * kInstrSize); 36851cb0ef41Sopenharmony_ci Instr instr_ori = instr_at(pc + 1 * kInstrSize); 36861cb0ef41Sopenharmony_ci Instr instr_ori2 = instr_at(pc + 3 * kInstrSize); 36871cb0ef41Sopenharmony_ci DCHECK(IsOri(instr_ori)); 36881cb0ef41Sopenharmony_ci DCHECK(IsOri(instr_ori2)); 36891cb0ef41Sopenharmony_ci // TODO(plind): symbolic names for the shifts. 36901cb0ef41Sopenharmony_ci int64_t imm = (instr_lui & static_cast<int64_t>(kImm16Mask)) << 48; 36911cb0ef41Sopenharmony_ci imm |= (instr_ori & static_cast<int64_t>(kImm16Mask)) << 32; 36921cb0ef41Sopenharmony_ci imm |= (instr_ori2 & static_cast<int64_t>(kImm16Mask)) << 16; 36931cb0ef41Sopenharmony_ci // Sign extend address. 36941cb0ef41Sopenharmony_ci imm >>= 16; 36951cb0ef41Sopenharmony_ci 36961cb0ef41Sopenharmony_ci if (imm == kEndOfJumpChain) { 36971cb0ef41Sopenharmony_ci return 0; // Number of instructions patched. 36981cb0ef41Sopenharmony_ci } 36991cb0ef41Sopenharmony_ci imm += pc_delta; 37001cb0ef41Sopenharmony_ci DCHECK_EQ(imm & 3, 0); 37011cb0ef41Sopenharmony_ci 37021cb0ef41Sopenharmony_ci instr_lui &= ~kImm16Mask; 37031cb0ef41Sopenharmony_ci instr_ori &= ~kImm16Mask; 37041cb0ef41Sopenharmony_ci instr_ori2 &= ~kImm16Mask; 37051cb0ef41Sopenharmony_ci 37061cb0ef41Sopenharmony_ci instr_at_put(pc + 0 * kInstrSize, instr_lui | ((imm >> 32) & kImm16Mask)); 37071cb0ef41Sopenharmony_ci instr_at_put(pc + 1 * kInstrSize, instr_ori | (imm >> 16 & kImm16Mask)); 37081cb0ef41Sopenharmony_ci instr_at_put(pc + 3 * kInstrSize, instr_ori2 | (imm & kImm16Mask)); 37091cb0ef41Sopenharmony_ci return 4; // Number of instructions patched. 37101cb0ef41Sopenharmony_ci } else if (IsJ(instr) || IsJal(instr)) { 37111cb0ef41Sopenharmony_ci // Regular j/jal relocation. 37121cb0ef41Sopenharmony_ci uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; 37131cb0ef41Sopenharmony_ci imm28 += pc_delta; 37141cb0ef41Sopenharmony_ci imm28 &= kImm28Mask; 37151cb0ef41Sopenharmony_ci instr &= ~kImm26Mask; 37161cb0ef41Sopenharmony_ci DCHECK_EQ(imm28 & 3, 0); 37171cb0ef41Sopenharmony_ci uint32_t imm26 = static_cast<uint32_t>(imm28 >> 2); 37181cb0ef41Sopenharmony_ci instr_at_put(pc, instr | (imm26 & kImm26Mask)); 37191cb0ef41Sopenharmony_ci return 1; // Number of instructions patched. 37201cb0ef41Sopenharmony_ci } else { 37211cb0ef41Sopenharmony_ci DCHECK(((instr & kJumpRawMask) == kJRawMark) || 37221cb0ef41Sopenharmony_ci ((instr & kJumpRawMask) == kJalRawMark)); 37231cb0ef41Sopenharmony_ci // Unbox raw offset and emit j/jal. 37241cb0ef41Sopenharmony_ci int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2; 37251cb0ef41Sopenharmony_ci // Sign extend 28-bit offset to 32-bit. 37261cb0ef41Sopenharmony_ci imm28 = (imm28 << 4) >> 4; 37271cb0ef41Sopenharmony_ci uint64_t target = 37281cb0ef41Sopenharmony_ci static_cast<int64_t>(imm28) + reinterpret_cast<uint64_t>(pc); 37291cb0ef41Sopenharmony_ci target &= kImm28Mask; 37301cb0ef41Sopenharmony_ci DCHECK_EQ(imm28 & 3, 0); 37311cb0ef41Sopenharmony_ci uint32_t imm26 = static_cast<uint32_t>(target >> 2); 37321cb0ef41Sopenharmony_ci // Check markings whether to emit j or jal. 37331cb0ef41Sopenharmony_ci uint32_t unbox = (instr & kJRawMark) ? J : JAL; 37341cb0ef41Sopenharmony_ci instr_at_put(pc, unbox | (imm26 & kImm26Mask)); 37351cb0ef41Sopenharmony_ci return 1; // Number of instructions patched. 37361cb0ef41Sopenharmony_ci } 37371cb0ef41Sopenharmony_ci} 37381cb0ef41Sopenharmony_ci 37391cb0ef41Sopenharmony_civoid Assembler::GrowBuffer() { 37401cb0ef41Sopenharmony_ci // Compute new buffer size. 37411cb0ef41Sopenharmony_ci int old_size = buffer_->size(); 37421cb0ef41Sopenharmony_ci int new_size = std::min(2 * old_size, old_size + 1 * MB); 37431cb0ef41Sopenharmony_ci 37441cb0ef41Sopenharmony_ci // Some internal data structures overflow for very large buffers, 37451cb0ef41Sopenharmony_ci // they must ensure that kMaximalBufferSize is not too large. 37461cb0ef41Sopenharmony_ci if (new_size > kMaximalBufferSize) { 37471cb0ef41Sopenharmony_ci V8::FatalProcessOutOfMemory(nullptr, "Assembler::GrowBuffer"); 37481cb0ef41Sopenharmony_ci } 37491cb0ef41Sopenharmony_ci 37501cb0ef41Sopenharmony_ci // Set up new buffer. 37511cb0ef41Sopenharmony_ci std::unique_ptr<AssemblerBuffer> new_buffer = buffer_->Grow(new_size); 37521cb0ef41Sopenharmony_ci DCHECK_EQ(new_size, new_buffer->size()); 37531cb0ef41Sopenharmony_ci byte* new_start = new_buffer->start(); 37541cb0ef41Sopenharmony_ci 37551cb0ef41Sopenharmony_ci // Copy the data. 37561cb0ef41Sopenharmony_ci intptr_t pc_delta = new_start - buffer_start_; 37571cb0ef41Sopenharmony_ci intptr_t rc_delta = (new_start + new_size) - (buffer_start_ + old_size); 37581cb0ef41Sopenharmony_ci size_t reloc_size = (buffer_start_ + old_size) - reloc_info_writer.pos(); 37591cb0ef41Sopenharmony_ci MemMove(new_start, buffer_start_, pc_offset()); 37601cb0ef41Sopenharmony_ci MemMove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(), 37611cb0ef41Sopenharmony_ci reloc_size); 37621cb0ef41Sopenharmony_ci 37631cb0ef41Sopenharmony_ci // Switch buffers. 37641cb0ef41Sopenharmony_ci buffer_ = std::move(new_buffer); 37651cb0ef41Sopenharmony_ci buffer_start_ = new_start; 37661cb0ef41Sopenharmony_ci pc_ += pc_delta; 37671cb0ef41Sopenharmony_ci pc_for_safepoint_ += pc_delta; 37681cb0ef41Sopenharmony_ci reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 37691cb0ef41Sopenharmony_ci reloc_info_writer.last_pc() + pc_delta); 37701cb0ef41Sopenharmony_ci 37711cb0ef41Sopenharmony_ci // Relocate runtime entries. 37721cb0ef41Sopenharmony_ci base::Vector<byte> instructions{buffer_start_, 37731cb0ef41Sopenharmony_ci static_cast<size_t>(pc_offset())}; 37741cb0ef41Sopenharmony_ci base::Vector<const byte> reloc_info{reloc_info_writer.pos(), reloc_size}; 37751cb0ef41Sopenharmony_ci for (RelocIterator it(instructions, reloc_info, 0); !it.done(); it.next()) { 37761cb0ef41Sopenharmony_ci RelocInfo::Mode rmode = it.rinfo()->rmode(); 37771cb0ef41Sopenharmony_ci if (rmode == RelocInfo::INTERNAL_REFERENCE) { 37781cb0ef41Sopenharmony_ci RelocateInternalReference(rmode, it.rinfo()->pc(), pc_delta); 37791cb0ef41Sopenharmony_ci } 37801cb0ef41Sopenharmony_ci } 37811cb0ef41Sopenharmony_ci 37821cb0ef41Sopenharmony_ci DCHECK(!overflow()); 37831cb0ef41Sopenharmony_ci} 37841cb0ef41Sopenharmony_ci 37851cb0ef41Sopenharmony_civoid Assembler::db(uint8_t data) { 37861cb0ef41Sopenharmony_ci CheckForEmitInForbiddenSlot(); 37871cb0ef41Sopenharmony_ci *reinterpret_cast<uint8_t*>(pc_) = data; 37881cb0ef41Sopenharmony_ci pc_ += sizeof(uint8_t); 37891cb0ef41Sopenharmony_ci} 37901cb0ef41Sopenharmony_ci 37911cb0ef41Sopenharmony_civoid Assembler::dd(uint32_t data, RelocInfo::Mode rmode) { 37921cb0ef41Sopenharmony_ci CheckForEmitInForbiddenSlot(); 37931cb0ef41Sopenharmony_ci if (!RelocInfo::IsNoInfo(rmode)) { 37941cb0ef41Sopenharmony_ci DCHECK(RelocInfo::IsDataEmbeddedObject(rmode) || 37951cb0ef41Sopenharmony_ci RelocInfo::IsLiteralConstant(rmode)); 37961cb0ef41Sopenharmony_ci RecordRelocInfo(rmode); 37971cb0ef41Sopenharmony_ci } 37981cb0ef41Sopenharmony_ci *reinterpret_cast<uint32_t*>(pc_) = data; 37991cb0ef41Sopenharmony_ci pc_ += sizeof(uint32_t); 38001cb0ef41Sopenharmony_ci} 38011cb0ef41Sopenharmony_ci 38021cb0ef41Sopenharmony_civoid Assembler::dq(uint64_t data, RelocInfo::Mode rmode) { 38031cb0ef41Sopenharmony_ci CheckForEmitInForbiddenSlot(); 38041cb0ef41Sopenharmony_ci if (!RelocInfo::IsNoInfo(rmode)) { 38051cb0ef41Sopenharmony_ci DCHECK(RelocInfo::IsDataEmbeddedObject(rmode) || 38061cb0ef41Sopenharmony_ci RelocInfo::IsLiteralConstant(rmode)); 38071cb0ef41Sopenharmony_ci RecordRelocInfo(rmode); 38081cb0ef41Sopenharmony_ci } 38091cb0ef41Sopenharmony_ci *reinterpret_cast<uint64_t*>(pc_) = data; 38101cb0ef41Sopenharmony_ci pc_ += sizeof(uint64_t); 38111cb0ef41Sopenharmony_ci} 38121cb0ef41Sopenharmony_ci 38131cb0ef41Sopenharmony_civoid Assembler::dd(Label* label) { 38141cb0ef41Sopenharmony_ci uint64_t data; 38151cb0ef41Sopenharmony_ci CheckForEmitInForbiddenSlot(); 38161cb0ef41Sopenharmony_ci if (label->is_bound()) { 38171cb0ef41Sopenharmony_ci data = reinterpret_cast<uint64_t>(buffer_start_ + label->pos()); 38181cb0ef41Sopenharmony_ci } else { 38191cb0ef41Sopenharmony_ci data = jump_address(label); 38201cb0ef41Sopenharmony_ci unbound_labels_count_++; 38211cb0ef41Sopenharmony_ci internal_reference_positions_.insert(label->pos()); 38221cb0ef41Sopenharmony_ci } 38231cb0ef41Sopenharmony_ci RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); 38241cb0ef41Sopenharmony_ci EmitHelper(data); 38251cb0ef41Sopenharmony_ci} 38261cb0ef41Sopenharmony_ci 38271cb0ef41Sopenharmony_civoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 38281cb0ef41Sopenharmony_ci if (!ShouldRecordRelocInfo(rmode)) return; 38291cb0ef41Sopenharmony_ci // We do not try to reuse pool constants. 38301cb0ef41Sopenharmony_ci RelocInfo rinfo(reinterpret_cast<Address>(pc_), rmode, data, Code()); 38311cb0ef41Sopenharmony_ci DCHECK_GE(buffer_space(), kMaxRelocSize); // Too late to grow buffer here. 38321cb0ef41Sopenharmony_ci reloc_info_writer.Write(&rinfo); 38331cb0ef41Sopenharmony_ci} 38341cb0ef41Sopenharmony_ci 38351cb0ef41Sopenharmony_civoid Assembler::BlockTrampolinePoolFor(int instructions) { 38361cb0ef41Sopenharmony_ci CheckTrampolinePoolQuick(instructions); 38371cb0ef41Sopenharmony_ci BlockTrampolinePoolBefore(pc_offset() + instructions * kInstrSize); 38381cb0ef41Sopenharmony_ci} 38391cb0ef41Sopenharmony_ci 38401cb0ef41Sopenharmony_civoid Assembler::CheckTrampolinePool() { 38411cb0ef41Sopenharmony_ci // Some small sequences of instructions must not be broken up by the 38421cb0ef41Sopenharmony_ci // insertion of a trampoline pool; such sequences are protected by setting 38431cb0ef41Sopenharmony_ci // either trampoline_pool_blocked_nesting_ or no_trampoline_pool_before_, 38441cb0ef41Sopenharmony_ci // which are both checked here. Also, recursive calls to CheckTrampolinePool 38451cb0ef41Sopenharmony_ci // are blocked by trampoline_pool_blocked_nesting_. 38461cb0ef41Sopenharmony_ci if ((trampoline_pool_blocked_nesting_ > 0) || 38471cb0ef41Sopenharmony_ci (pc_offset() < no_trampoline_pool_before_)) { 38481cb0ef41Sopenharmony_ci // Emission is currently blocked; make sure we try again as soon as 38491cb0ef41Sopenharmony_ci // possible. 38501cb0ef41Sopenharmony_ci if (trampoline_pool_blocked_nesting_ > 0) { 38511cb0ef41Sopenharmony_ci next_buffer_check_ = pc_offset() + kInstrSize; 38521cb0ef41Sopenharmony_ci } else { 38531cb0ef41Sopenharmony_ci next_buffer_check_ = no_trampoline_pool_before_; 38541cb0ef41Sopenharmony_ci } 38551cb0ef41Sopenharmony_ci return; 38561cb0ef41Sopenharmony_ci } 38571cb0ef41Sopenharmony_ci 38581cb0ef41Sopenharmony_ci DCHECK(!trampoline_emitted_); 38591cb0ef41Sopenharmony_ci DCHECK_GE(unbound_labels_count_, 0); 38601cb0ef41Sopenharmony_ci if (unbound_labels_count_ > 0) { 38611cb0ef41Sopenharmony_ci // First we emit jump (2 instructions), then we emit trampoline pool. 38621cb0ef41Sopenharmony_ci { 38631cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 38641cb0ef41Sopenharmony_ci Label after_pool; 38651cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 38661cb0ef41Sopenharmony_ci bc(&after_pool); 38671cb0ef41Sopenharmony_ci } else { 38681cb0ef41Sopenharmony_ci b(&after_pool); 38691cb0ef41Sopenharmony_ci } 38701cb0ef41Sopenharmony_ci nop(); 38711cb0ef41Sopenharmony_ci 38721cb0ef41Sopenharmony_ci int pool_start = pc_offset(); 38731cb0ef41Sopenharmony_ci for (int i = 0; i < unbound_labels_count_; i++) { 38741cb0ef41Sopenharmony_ci { 38751cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 38761cb0ef41Sopenharmony_ci bc(&after_pool); 38771cb0ef41Sopenharmony_ci nop(); 38781cb0ef41Sopenharmony_ci } else { 38791cb0ef41Sopenharmony_ci or_(t8, ra, zero_reg); 38801cb0ef41Sopenharmony_ci nal(); // Read PC into ra register. 38811cb0ef41Sopenharmony_ci lui(t9, 0); // Branch delay slot. 38821cb0ef41Sopenharmony_ci ori(t9, t9, 0); 38831cb0ef41Sopenharmony_ci daddu(t9, ra, t9); 38841cb0ef41Sopenharmony_ci or_(ra, t8, zero_reg); 38851cb0ef41Sopenharmony_ci // Instruction jr will take or_ from the next trampoline. 38861cb0ef41Sopenharmony_ci // in its branch delay slot. This is the expected behavior 38871cb0ef41Sopenharmony_ci // in order to decrease size of trampoline pool. 38881cb0ef41Sopenharmony_ci jr(t9); 38891cb0ef41Sopenharmony_ci } 38901cb0ef41Sopenharmony_ci } 38911cb0ef41Sopenharmony_ci } 38921cb0ef41Sopenharmony_ci nop(); 38931cb0ef41Sopenharmony_ci // If unbound_labels_count_ is big enough, label after_pool will 38941cb0ef41Sopenharmony_ci // need a trampoline too, so we must create the trampoline before 38951cb0ef41Sopenharmony_ci // the bind operation to make sure function 'bind' can get this 38961cb0ef41Sopenharmony_ci // information. 38971cb0ef41Sopenharmony_ci trampoline_ = Trampoline(pool_start, unbound_labels_count_); 38981cb0ef41Sopenharmony_ci bind(&after_pool); 38991cb0ef41Sopenharmony_ci 39001cb0ef41Sopenharmony_ci trampoline_emitted_ = true; 39011cb0ef41Sopenharmony_ci // As we are only going to emit trampoline once, we need to prevent any 39021cb0ef41Sopenharmony_ci // further emission. 39031cb0ef41Sopenharmony_ci next_buffer_check_ = kMaxInt; 39041cb0ef41Sopenharmony_ci } 39051cb0ef41Sopenharmony_ci } else { 39061cb0ef41Sopenharmony_ci // Number of branches to unbound label at this point is zero, so we can 39071cb0ef41Sopenharmony_ci // move next buffer check to maximum. 39081cb0ef41Sopenharmony_ci next_buffer_check_ = 39091cb0ef41Sopenharmony_ci pc_offset() + kMaxBranchOffset - kTrampolineSlotsSize * 16; 39101cb0ef41Sopenharmony_ci } 39111cb0ef41Sopenharmony_ci return; 39121cb0ef41Sopenharmony_ci} 39131cb0ef41Sopenharmony_ci 39141cb0ef41Sopenharmony_ciAddress Assembler::target_address_at(Address pc) { 39151cb0ef41Sopenharmony_ci Instr instr0 = instr_at(pc); 39161cb0ef41Sopenharmony_ci Instr instr1 = instr_at(pc + 1 * kInstrSize); 39171cb0ef41Sopenharmony_ci Instr instr3 = instr_at(pc + 3 * kInstrSize); 39181cb0ef41Sopenharmony_ci 39191cb0ef41Sopenharmony_ci // Interpret 4 instructions for address generated by li: See listing in 39201cb0ef41Sopenharmony_ci // Assembler::set_target_address_at() just below. 39211cb0ef41Sopenharmony_ci if ((GetOpcodeField(instr0) == LUI) && (GetOpcodeField(instr1) == ORI) && 39221cb0ef41Sopenharmony_ci (GetOpcodeField(instr3) == ORI)) { 39231cb0ef41Sopenharmony_ci // Assemble the 48 bit value. 39241cb0ef41Sopenharmony_ci int64_t addr = 39251cb0ef41Sopenharmony_ci static_cast<int64_t>(((uint64_t)(GetImmediate16(instr0)) << 32) | 39261cb0ef41Sopenharmony_ci ((uint64_t)(GetImmediate16(instr1)) << 16) | 39271cb0ef41Sopenharmony_ci ((uint64_t)(GetImmediate16(instr3)))); 39281cb0ef41Sopenharmony_ci 39291cb0ef41Sopenharmony_ci // Sign extend to get canonical address. 39301cb0ef41Sopenharmony_ci addr = (addr << 16) >> 16; 39311cb0ef41Sopenharmony_ci return static_cast<Address>(addr); 39321cb0ef41Sopenharmony_ci } 39331cb0ef41Sopenharmony_ci // We should never get here, force a bad address if we do. 39341cb0ef41Sopenharmony_ci UNREACHABLE(); 39351cb0ef41Sopenharmony_ci} 39361cb0ef41Sopenharmony_ci 39371cb0ef41Sopenharmony_ci// On Mips64, a target address is stored in a 4-instruction sequence: 39381cb0ef41Sopenharmony_ci// 0: lui(rd, (j.imm64_ >> 32) & kImm16Mask); 39391cb0ef41Sopenharmony_ci// 1: ori(rd, rd, (j.imm64_ >> 16) & kImm16Mask); 39401cb0ef41Sopenharmony_ci// 2: dsll(rd, rd, 16); 39411cb0ef41Sopenharmony_ci// 3: ori(rd, rd, j.imm32_ & kImm16Mask); 39421cb0ef41Sopenharmony_ci// 39431cb0ef41Sopenharmony_ci// Patching the address must replace all the lui & ori instructions, 39441cb0ef41Sopenharmony_ci// and flush the i-cache. 39451cb0ef41Sopenharmony_ci// 39461cb0ef41Sopenharmony_ci// There is an optimization below, which emits a nop when the address 39471cb0ef41Sopenharmony_ci// fits in just 16 bits. This is unlikely to help, and should be benchmarked, 39481cb0ef41Sopenharmony_ci// and possibly removed. 39491cb0ef41Sopenharmony_civoid Assembler::set_target_value_at(Address pc, uint64_t target, 39501cb0ef41Sopenharmony_ci ICacheFlushMode icache_flush_mode) { 39511cb0ef41Sopenharmony_ci // There is an optimization where only 4 instructions are used to load address 39521cb0ef41Sopenharmony_ci // in code on MIP64 because only 48-bits of address is effectively used. 39531cb0ef41Sopenharmony_ci // It relies on fact the upper [63:48] bits are not used for virtual address 39541cb0ef41Sopenharmony_ci // translation and they have to be set according to value of bit 47 in order 39551cb0ef41Sopenharmony_ci // get canonical address. 39561cb0ef41Sopenharmony_ci Instr instr1 = instr_at(pc + kInstrSize); 39571cb0ef41Sopenharmony_ci uint32_t rt_code = GetRt(instr1); 39581cb0ef41Sopenharmony_ci uint32_t* p = reinterpret_cast<uint32_t*>(pc); 39591cb0ef41Sopenharmony_ci 39601cb0ef41Sopenharmony_ci#ifdef DEBUG 39611cb0ef41Sopenharmony_ci // Check we have the result from a li macro-instruction. 39621cb0ef41Sopenharmony_ci Instr instr0 = instr_at(pc); 39631cb0ef41Sopenharmony_ci Instr instr3 = instr_at(pc + kInstrSize * 3); 39641cb0ef41Sopenharmony_ci DCHECK((GetOpcodeField(instr0) == LUI && GetOpcodeField(instr1) == ORI && 39651cb0ef41Sopenharmony_ci GetOpcodeField(instr3) == ORI)); 39661cb0ef41Sopenharmony_ci#endif 39671cb0ef41Sopenharmony_ci 39681cb0ef41Sopenharmony_ci // Must use 4 instructions to insure patchable code. 39691cb0ef41Sopenharmony_ci // lui rt, upper-16. 39701cb0ef41Sopenharmony_ci // ori rt, rt, lower-16. 39711cb0ef41Sopenharmony_ci // dsll rt, rt, 16. 39721cb0ef41Sopenharmony_ci // ori rt rt, lower-16. 39731cb0ef41Sopenharmony_ci *p = LUI | (rt_code << kRtShift) | ((target >> 32) & kImm16Mask); 39741cb0ef41Sopenharmony_ci *(p + 1) = ORI | (rt_code << kRtShift) | (rt_code << kRsShift) | 39751cb0ef41Sopenharmony_ci ((target >> 16) & kImm16Mask); 39761cb0ef41Sopenharmony_ci *(p + 3) = ORI | (rt_code << kRsShift) | (rt_code << kRtShift) | 39771cb0ef41Sopenharmony_ci (target & kImm16Mask); 39781cb0ef41Sopenharmony_ci 39791cb0ef41Sopenharmony_ci if (icache_flush_mode != SKIP_ICACHE_FLUSH) { 39801cb0ef41Sopenharmony_ci FlushInstructionCache(pc, 4 * kInstrSize); 39811cb0ef41Sopenharmony_ci } 39821cb0ef41Sopenharmony_ci} 39831cb0ef41Sopenharmony_ci 39841cb0ef41Sopenharmony_ciUseScratchRegisterScope::UseScratchRegisterScope(Assembler* assembler) 39851cb0ef41Sopenharmony_ci : available_(assembler->GetScratchRegisterList()), 39861cb0ef41Sopenharmony_ci old_available_(*available_) {} 39871cb0ef41Sopenharmony_ci 39881cb0ef41Sopenharmony_ciUseScratchRegisterScope::~UseScratchRegisterScope() { 39891cb0ef41Sopenharmony_ci *available_ = old_available_; 39901cb0ef41Sopenharmony_ci} 39911cb0ef41Sopenharmony_ci 39921cb0ef41Sopenharmony_ciRegister UseScratchRegisterScope::Acquire() { 39931cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(available_); 39941cb0ef41Sopenharmony_ci return available_->PopFirst(); 39951cb0ef41Sopenharmony_ci} 39961cb0ef41Sopenharmony_ci 39971cb0ef41Sopenharmony_cibool UseScratchRegisterScope::hasAvailable() const { 39981cb0ef41Sopenharmony_ci return !available_->is_empty(); 39991cb0ef41Sopenharmony_ci} 40001cb0ef41Sopenharmony_ci 40011cb0ef41Sopenharmony_ciLoadStoreLaneParams::LoadStoreLaneParams(MachineRepresentation rep, 40021cb0ef41Sopenharmony_ci uint8_t laneidx) { 40031cb0ef41Sopenharmony_ci switch (rep) { 40041cb0ef41Sopenharmony_ci case MachineRepresentation::kWord8: 40051cb0ef41Sopenharmony_ci *this = LoadStoreLaneParams(laneidx, MSA_B, 16); 40061cb0ef41Sopenharmony_ci break; 40071cb0ef41Sopenharmony_ci case MachineRepresentation::kWord16: 40081cb0ef41Sopenharmony_ci *this = LoadStoreLaneParams(laneidx, MSA_H, 8); 40091cb0ef41Sopenharmony_ci break; 40101cb0ef41Sopenharmony_ci case MachineRepresentation::kWord32: 40111cb0ef41Sopenharmony_ci *this = LoadStoreLaneParams(laneidx, MSA_W, 4); 40121cb0ef41Sopenharmony_ci break; 40131cb0ef41Sopenharmony_ci case MachineRepresentation::kWord64: 40141cb0ef41Sopenharmony_ci *this = LoadStoreLaneParams(laneidx, MSA_D, 2); 40151cb0ef41Sopenharmony_ci break; 40161cb0ef41Sopenharmony_ci default: 40171cb0ef41Sopenharmony_ci UNREACHABLE(); 40181cb0ef41Sopenharmony_ci } 40191cb0ef41Sopenharmony_ci} 40201cb0ef41Sopenharmony_ci 40211cb0ef41Sopenharmony_ci} // namespace internal 40221cb0ef41Sopenharmony_ci} // namespace v8 40231cb0ef41Sopenharmony_ci 40241cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_MIPS64 4025