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