11cb0ef41Sopenharmony_ci// Copyright 2012 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include <limits.h> // For LONG_MIN, LONG_MAX. 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_MIPS64 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "src/base/bits.h" 101cb0ef41Sopenharmony_ci#include "src/base/division-by-constant.h" 111cb0ef41Sopenharmony_ci#include "src/codegen/assembler-inl.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/callable.h" 131cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h" 141cb0ef41Sopenharmony_ci#include "src/codegen/external-reference-table.h" 151cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors-inl.h" 161cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h" 171cb0ef41Sopenharmony_ci#include "src/codegen/register-configuration.h" 181cb0ef41Sopenharmony_ci#include "src/debug/debug.h" 191cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimizer.h" 201cb0ef41Sopenharmony_ci#include "src/execution/frames-inl.h" 211cb0ef41Sopenharmony_ci#include "src/heap/memory-chunk.h" 221cb0ef41Sopenharmony_ci#include "src/init/bootstrapper.h" 231cb0ef41Sopenharmony_ci#include "src/logging/counters.h" 241cb0ef41Sopenharmony_ci#include "src/objects/heap-number.h" 251cb0ef41Sopenharmony_ci#include "src/runtime/runtime.h" 261cb0ef41Sopenharmony_ci#include "src/snapshot/snapshot.h" 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 291cb0ef41Sopenharmony_ci#include "src/wasm/wasm-code-manager.h" 301cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci// Satisfy cpplint check, but don't include platform-specific header. It is 331cb0ef41Sopenharmony_ci// included recursively via macro-assembler.h. 341cb0ef41Sopenharmony_ci#if 0 351cb0ef41Sopenharmony_ci#include "src/codegen/mips64/macro-assembler-mips64.h" 361cb0ef41Sopenharmony_ci#endif 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_cinamespace v8 { 391cb0ef41Sopenharmony_cinamespace internal { 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_cistatic inline bool IsZero(const Operand& rt) { 421cb0ef41Sopenharmony_ci if (rt.is_reg()) { 431cb0ef41Sopenharmony_ci return rt.rm() == zero_reg; 441cb0ef41Sopenharmony_ci } else { 451cb0ef41Sopenharmony_ci return rt.immediate() == 0; 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci} 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ciint TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode, 501cb0ef41Sopenharmony_ci Register exclusion1, 511cb0ef41Sopenharmony_ci Register exclusion2, 521cb0ef41Sopenharmony_ci Register exclusion3) const { 531cb0ef41Sopenharmony_ci int bytes = 0; 541cb0ef41Sopenharmony_ci RegList exclusions = {exclusion1, exclusion2, exclusion3}; 551cb0ef41Sopenharmony_ci RegList list = kJSCallerSaved - exclusions; 561cb0ef41Sopenharmony_ci bytes += list.Count() * kPointerSize; 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci if (fp_mode == SaveFPRegsMode::kSave) { 591cb0ef41Sopenharmony_ci bytes += kCallerSavedFPU.Count() * kDoubleSize; 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci return bytes; 631cb0ef41Sopenharmony_ci} 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ciint TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1, 661cb0ef41Sopenharmony_ci Register exclusion2, Register exclusion3) { 671cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 681cb0ef41Sopenharmony_ci int bytes = 0; 691cb0ef41Sopenharmony_ci RegList exclusions = {exclusion1, exclusion2, exclusion3}; 701cb0ef41Sopenharmony_ci RegList list = kJSCallerSaved - exclusions; 711cb0ef41Sopenharmony_ci MultiPush(list); 721cb0ef41Sopenharmony_ci bytes += list.Count() * kPointerSize; 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci if (fp_mode == SaveFPRegsMode::kSave) { 751cb0ef41Sopenharmony_ci MultiPushFPU(kCallerSavedFPU); 761cb0ef41Sopenharmony_ci bytes += kCallerSavedFPU.Count() * kDoubleSize; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci return bytes; 801cb0ef41Sopenharmony_ci} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ciint TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1, 831cb0ef41Sopenharmony_ci Register exclusion2, Register exclusion3) { 841cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 851cb0ef41Sopenharmony_ci int bytes = 0; 861cb0ef41Sopenharmony_ci if (fp_mode == SaveFPRegsMode::kSave) { 871cb0ef41Sopenharmony_ci MultiPopFPU(kCallerSavedFPU); 881cb0ef41Sopenharmony_ci bytes += kCallerSavedFPU.Count() * kDoubleSize; 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci RegList exclusions = {exclusion1, exclusion2, exclusion3}; 921cb0ef41Sopenharmony_ci RegList list = kJSCallerSaved - exclusions; 931cb0ef41Sopenharmony_ci MultiPop(list); 941cb0ef41Sopenharmony_ci bytes += list.Count() * kPointerSize; 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci return bytes; 971cb0ef41Sopenharmony_ci} 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_civoid TurboAssembler::LoadRoot(Register destination, RootIndex index) { 1001cb0ef41Sopenharmony_ci Ld(destination, MemOperand(s6, RootRegisterOffsetForRootIndex(index))); 1011cb0ef41Sopenharmony_ci} 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_civoid TurboAssembler::LoadRoot(Register destination, RootIndex index, 1041cb0ef41Sopenharmony_ci Condition cond, Register src1, 1051cb0ef41Sopenharmony_ci const Operand& src2) { 1061cb0ef41Sopenharmony_ci Branch(2, NegateCondition(cond), src1, src2); 1071cb0ef41Sopenharmony_ci Ld(destination, MemOperand(s6, RootRegisterOffsetForRootIndex(index))); 1081cb0ef41Sopenharmony_ci} 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_civoid TurboAssembler::PushCommonFrame(Register marker_reg) { 1111cb0ef41Sopenharmony_ci if (marker_reg.is_valid()) { 1121cb0ef41Sopenharmony_ci Push(ra, fp, marker_reg); 1131cb0ef41Sopenharmony_ci Daddu(fp, sp, Operand(kPointerSize)); 1141cb0ef41Sopenharmony_ci } else { 1151cb0ef41Sopenharmony_ci Push(ra, fp); 1161cb0ef41Sopenharmony_ci mov(fp, sp); 1171cb0ef41Sopenharmony_ci } 1181cb0ef41Sopenharmony_ci} 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_civoid TurboAssembler::PushStandardFrame(Register function_reg) { 1211cb0ef41Sopenharmony_ci int offset = -StandardFrameConstants::kContextOffset; 1221cb0ef41Sopenharmony_ci if (function_reg.is_valid()) { 1231cb0ef41Sopenharmony_ci Push(ra, fp, cp, function_reg, kJavaScriptCallArgCountRegister); 1241cb0ef41Sopenharmony_ci offset += 2 * kPointerSize; 1251cb0ef41Sopenharmony_ci } else { 1261cb0ef41Sopenharmony_ci Push(ra, fp, cp, kJavaScriptCallArgCountRegister); 1271cb0ef41Sopenharmony_ci offset += kPointerSize; 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci Daddu(fp, sp, Operand(offset)); 1301cb0ef41Sopenharmony_ci} 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci// Clobbers object, dst, value, and ra, if (ra_status == kRAHasBeenSaved) 1331cb0ef41Sopenharmony_ci// The register 'object' contains a heap object pointer. The heap object 1341cb0ef41Sopenharmony_ci// tag is shifted away. 1351cb0ef41Sopenharmony_civoid MacroAssembler::RecordWriteField(Register object, int offset, 1361cb0ef41Sopenharmony_ci Register value, Register dst, 1371cb0ef41Sopenharmony_ci RAStatus ra_status, 1381cb0ef41Sopenharmony_ci SaveFPRegsMode save_fp, 1391cb0ef41Sopenharmony_ci RememberedSetAction remembered_set_action, 1401cb0ef41Sopenharmony_ci SmiCheck smi_check) { 1411cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 1421cb0ef41Sopenharmony_ci DCHECK(!AreAliased(value, dst, t8, object)); 1431cb0ef41Sopenharmony_ci // First, check if a write barrier is even needed. The tests below 1441cb0ef41Sopenharmony_ci // catch stores of Smis. 1451cb0ef41Sopenharmony_ci Label done; 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci // Skip barrier if writing a smi. 1481cb0ef41Sopenharmony_ci if (smi_check == SmiCheck::kInline) { 1491cb0ef41Sopenharmony_ci JumpIfSmi(value, &done); 1501cb0ef41Sopenharmony_ci } 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci // Although the object register is tagged, the offset is relative to the start 1531cb0ef41Sopenharmony_ci // of the object, so offset must be a multiple of kPointerSize. 1541cb0ef41Sopenharmony_ci DCHECK(IsAligned(offset, kPointerSize)); 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci Daddu(dst, object, Operand(offset - kHeapObjectTag)); 1571cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 1581cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 1591cb0ef41Sopenharmony_ci Label ok; 1601cb0ef41Sopenharmony_ci And(t8, dst, Operand(kPointerSize - 1)); 1611cb0ef41Sopenharmony_ci Branch(&ok, eq, t8, Operand(zero_reg)); 1621cb0ef41Sopenharmony_ci stop(); 1631cb0ef41Sopenharmony_ci bind(&ok); 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci RecordWrite(object, dst, value, ra_status, save_fp, remembered_set_action, 1671cb0ef41Sopenharmony_ci SmiCheck::kOmit); 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci bind(&done); 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci // Clobber clobbered input registers when running with the debug-code flag 1721cb0ef41Sopenharmony_ci // turned on to provoke errors. 1731cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 1741cb0ef41Sopenharmony_ci li(value, Operand(bit_cast<int64_t>(kZapValue + 4))); 1751cb0ef41Sopenharmony_ci li(dst, Operand(bit_cast<int64_t>(kZapValue + 8))); 1761cb0ef41Sopenharmony_ci } 1771cb0ef41Sopenharmony_ci} 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_civoid TurboAssembler::MaybeSaveRegisters(RegList registers) { 1801cb0ef41Sopenharmony_ci if (registers.is_empty()) return; 1811cb0ef41Sopenharmony_ci MultiPush(registers); 1821cb0ef41Sopenharmony_ci} 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_civoid TurboAssembler::MaybeRestoreRegisters(RegList registers) { 1851cb0ef41Sopenharmony_ci if (registers.is_empty()) return; 1861cb0ef41Sopenharmony_ci MultiPop(registers); 1871cb0ef41Sopenharmony_ci} 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_civoid TurboAssembler::CallEphemeronKeyBarrier(Register object, 1901cb0ef41Sopenharmony_ci Register slot_address, 1911cb0ef41Sopenharmony_ci SaveFPRegsMode fp_mode) { 1921cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 1931cb0ef41Sopenharmony_ci DCHECK(!AreAliased(object, slot_address)); 1941cb0ef41Sopenharmony_ci RegList registers = 1951cb0ef41Sopenharmony_ci WriteBarrierDescriptor::ComputeSavedRegisters(object, slot_address); 1961cb0ef41Sopenharmony_ci MaybeSaveRegisters(registers); 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci Register object_parameter = WriteBarrierDescriptor::ObjectRegister(); 1991cb0ef41Sopenharmony_ci Register slot_address_parameter = 2001cb0ef41Sopenharmony_ci WriteBarrierDescriptor::SlotAddressRegister(); 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci Push(object); 2031cb0ef41Sopenharmony_ci Push(slot_address); 2041cb0ef41Sopenharmony_ci Pop(slot_address_parameter); 2051cb0ef41Sopenharmony_ci Pop(object_parameter); 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci Call(isolate()->builtins()->code_handle( 2081cb0ef41Sopenharmony_ci Builtins::GetEphemeronKeyBarrierStub(fp_mode)), 2091cb0ef41Sopenharmony_ci RelocInfo::CODE_TARGET); 2101cb0ef41Sopenharmony_ci MaybeRestoreRegisters(registers); 2111cb0ef41Sopenharmony_ci} 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_civoid TurboAssembler::CallRecordWriteStubSaveRegisters( 2141cb0ef41Sopenharmony_ci Register object, Register slot_address, 2151cb0ef41Sopenharmony_ci RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode, 2161cb0ef41Sopenharmony_ci StubCallMode mode) { 2171cb0ef41Sopenharmony_ci DCHECK(!AreAliased(object, slot_address)); 2181cb0ef41Sopenharmony_ci RegList registers = 2191cb0ef41Sopenharmony_ci WriteBarrierDescriptor::ComputeSavedRegisters(object, slot_address); 2201cb0ef41Sopenharmony_ci MaybeSaveRegisters(registers); 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci Register object_parameter = WriteBarrierDescriptor::ObjectRegister(); 2231cb0ef41Sopenharmony_ci Register slot_address_parameter = 2241cb0ef41Sopenharmony_ci WriteBarrierDescriptor::SlotAddressRegister(); 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci Push(object); 2271cb0ef41Sopenharmony_ci Push(slot_address); 2281cb0ef41Sopenharmony_ci Pop(slot_address_parameter); 2291cb0ef41Sopenharmony_ci Pop(object_parameter); 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci CallRecordWriteStub(object_parameter, slot_address_parameter, 2321cb0ef41Sopenharmony_ci remembered_set_action, fp_mode, mode); 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci MaybeRestoreRegisters(registers); 2351cb0ef41Sopenharmony_ci} 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_civoid TurboAssembler::CallRecordWriteStub( 2381cb0ef41Sopenharmony_ci Register object, Register slot_address, 2391cb0ef41Sopenharmony_ci RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode, 2401cb0ef41Sopenharmony_ci StubCallMode mode) { 2411cb0ef41Sopenharmony_ci // Use CallRecordWriteStubSaveRegisters if the object and slot registers 2421cb0ef41Sopenharmony_ci // need to be caller saved. 2431cb0ef41Sopenharmony_ci DCHECK_EQ(WriteBarrierDescriptor::ObjectRegister(), object); 2441cb0ef41Sopenharmony_ci DCHECK_EQ(WriteBarrierDescriptor::SlotAddressRegister(), slot_address); 2451cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 2461cb0ef41Sopenharmony_ci if (mode == StubCallMode::kCallWasmRuntimeStub) { 2471cb0ef41Sopenharmony_ci auto wasm_target = 2481cb0ef41Sopenharmony_ci wasm::WasmCode::GetRecordWriteStub(remembered_set_action, fp_mode); 2491cb0ef41Sopenharmony_ci Call(wasm_target, RelocInfo::WASM_STUB_CALL); 2501cb0ef41Sopenharmony_ci#else 2511cb0ef41Sopenharmony_ci if (false) { 2521cb0ef41Sopenharmony_ci#endif 2531cb0ef41Sopenharmony_ci } else { 2541cb0ef41Sopenharmony_ci auto builtin = Builtins::GetRecordWriteStub(remembered_set_action, fp_mode); 2551cb0ef41Sopenharmony_ci if (options().inline_offheap_trampolines) { 2561cb0ef41Sopenharmony_ci // Inline the trampoline. 2571cb0ef41Sopenharmony_ci RecordCommentForOffHeapTrampoline(builtin); 2581cb0ef41Sopenharmony_ci li(t9, Operand(BuiltinEntry(builtin), RelocInfo::OFF_HEAP_TARGET)); 2591cb0ef41Sopenharmony_ci Call(t9); 2601cb0ef41Sopenharmony_ci RecordComment("]"); 2611cb0ef41Sopenharmony_ci } else { 2621cb0ef41Sopenharmony_ci Handle<Code> code_target = isolate()->builtins()->code_handle(builtin); 2631cb0ef41Sopenharmony_ci Call(code_target, RelocInfo::CODE_TARGET); 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci } 2661cb0ef41Sopenharmony_ci} 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci// Clobbers object, address, value, and ra, if (ra_status == kRAHasBeenSaved) 2691cb0ef41Sopenharmony_ci// The register 'object' contains a heap object pointer. The heap object 2701cb0ef41Sopenharmony_ci// tag is shifted away. 2711cb0ef41Sopenharmony_civoid MacroAssembler::RecordWrite(Register object, Register address, 2721cb0ef41Sopenharmony_ci Register value, RAStatus ra_status, 2731cb0ef41Sopenharmony_ci SaveFPRegsMode fp_mode, 2741cb0ef41Sopenharmony_ci RememberedSetAction remembered_set_action, 2751cb0ef41Sopenharmony_ci SmiCheck smi_check) { 2761cb0ef41Sopenharmony_ci DCHECK(!AreAliased(object, address, value, t8)); 2771cb0ef41Sopenharmony_ci DCHECK(!AreAliased(object, address, value, t9)); 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 2801cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 2811cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 2821cb0ef41Sopenharmony_ci DCHECK(!AreAliased(object, value, scratch)); 2831cb0ef41Sopenharmony_ci Ld(scratch, MemOperand(address)); 2841cb0ef41Sopenharmony_ci Assert(eq, AbortReason::kWrongAddressOrValuePassedToRecordWrite, scratch, 2851cb0ef41Sopenharmony_ci Operand(value)); 2861cb0ef41Sopenharmony_ci } 2871cb0ef41Sopenharmony_ci 2881cb0ef41Sopenharmony_ci if ((remembered_set_action == RememberedSetAction::kOmit && 2891cb0ef41Sopenharmony_ci !FLAG_incremental_marking) || 2901cb0ef41Sopenharmony_ci FLAG_disable_write_barriers) { 2911cb0ef41Sopenharmony_ci return; 2921cb0ef41Sopenharmony_ci } 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci // First, check if a write barrier is even needed. The tests below 2951cb0ef41Sopenharmony_ci // catch stores of smis and stores into the young generation. 2961cb0ef41Sopenharmony_ci Label done; 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci if (smi_check == SmiCheck::kInline) { 2991cb0ef41Sopenharmony_ci DCHECK_EQ(0, kSmiTag); 3001cb0ef41Sopenharmony_ci JumpIfSmi(value, &done); 3011cb0ef41Sopenharmony_ci } 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_ci CheckPageFlag(value, 3041cb0ef41Sopenharmony_ci value, // Used as scratch. 3051cb0ef41Sopenharmony_ci MemoryChunk::kPointersToHereAreInterestingMask, eq, &done); 3061cb0ef41Sopenharmony_ci CheckPageFlag(object, 3071cb0ef41Sopenharmony_ci value, // Used as scratch. 3081cb0ef41Sopenharmony_ci MemoryChunk::kPointersFromHereAreInterestingMask, eq, &done); 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci // Record the actual write. 3111cb0ef41Sopenharmony_ci if (ra_status == kRAHasNotBeenSaved) { 3121cb0ef41Sopenharmony_ci push(ra); 3131cb0ef41Sopenharmony_ci } 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci Register slot_address = WriteBarrierDescriptor::SlotAddressRegister(); 3161cb0ef41Sopenharmony_ci DCHECK(!AreAliased(object, slot_address, value)); 3171cb0ef41Sopenharmony_ci mov(slot_address, address); 3181cb0ef41Sopenharmony_ci CallRecordWriteStub(object, slot_address, remembered_set_action, fp_mode); 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci if (ra_status == kRAHasNotBeenSaved) { 3211cb0ef41Sopenharmony_ci pop(ra); 3221cb0ef41Sopenharmony_ci } 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ci bind(&done); 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci // Clobber clobbered registers when running with the debug-code flag 3271cb0ef41Sopenharmony_ci // turned on to provoke errors. 3281cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 3291cb0ef41Sopenharmony_ci li(address, Operand(bit_cast<int64_t>(kZapValue + 12))); 3301cb0ef41Sopenharmony_ci li(value, Operand(bit_cast<int64_t>(kZapValue + 16))); 3311cb0ef41Sopenharmony_ci li(slot_address, Operand(bit_cast<int64_t>(kZapValue + 20))); 3321cb0ef41Sopenharmony_ci } 3331cb0ef41Sopenharmony_ci} 3341cb0ef41Sopenharmony_ci 3351cb0ef41Sopenharmony_ci// --------------------------------------------------------------------------- 3361cb0ef41Sopenharmony_ci// Instruction macros. 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_civoid TurboAssembler::Addu(Register rd, Register rs, const Operand& rt) { 3391cb0ef41Sopenharmony_ci if (rt.is_reg()) { 3401cb0ef41Sopenharmony_ci addu(rd, rs, rt.rm()); 3411cb0ef41Sopenharmony_ci } else { 3421cb0ef41Sopenharmony_ci if (is_int16(rt.immediate()) && !MustUseReg(rt.rmode())) { 3431cb0ef41Sopenharmony_ci addiu(rd, rs, static_cast<int32_t>(rt.immediate())); 3441cb0ef41Sopenharmony_ci } else { 3451cb0ef41Sopenharmony_ci // li handles the relocation. 3461cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 3471cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 3481cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 3491cb0ef41Sopenharmony_ci li(scratch, rt); 3501cb0ef41Sopenharmony_ci addu(rd, rs, scratch); 3511cb0ef41Sopenharmony_ci } 3521cb0ef41Sopenharmony_ci } 3531cb0ef41Sopenharmony_ci} 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_civoid TurboAssembler::Daddu(Register rd, Register rs, const Operand& rt) { 3561cb0ef41Sopenharmony_ci if (rt.is_reg()) { 3571cb0ef41Sopenharmony_ci daddu(rd, rs, rt.rm()); 3581cb0ef41Sopenharmony_ci } else { 3591cb0ef41Sopenharmony_ci if (is_int16(rt.immediate()) && !MustUseReg(rt.rmode())) { 3601cb0ef41Sopenharmony_ci daddiu(rd, rs, static_cast<int32_t>(rt.immediate())); 3611cb0ef41Sopenharmony_ci } else { 3621cb0ef41Sopenharmony_ci // li handles the relocation. 3631cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 3641cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 3651cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 3661cb0ef41Sopenharmony_ci li(scratch, rt); 3671cb0ef41Sopenharmony_ci daddu(rd, rs, scratch); 3681cb0ef41Sopenharmony_ci } 3691cb0ef41Sopenharmony_ci } 3701cb0ef41Sopenharmony_ci} 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_civoid TurboAssembler::Subu(Register rd, Register rs, const Operand& rt) { 3731cb0ef41Sopenharmony_ci if (rt.is_reg()) { 3741cb0ef41Sopenharmony_ci subu(rd, rs, rt.rm()); 3751cb0ef41Sopenharmony_ci } else { 3761cb0ef41Sopenharmony_ci DCHECK(is_int32(rt.immediate())); 3771cb0ef41Sopenharmony_ci if (is_int16(-rt.immediate()) && !MustUseReg(rt.rmode())) { 3781cb0ef41Sopenharmony_ci addiu(rd, rs, 3791cb0ef41Sopenharmony_ci static_cast<int32_t>( 3801cb0ef41Sopenharmony_ci -rt.immediate())); // No subiu instr, use addiu(x, y, -imm). 3811cb0ef41Sopenharmony_ci } else { 3821cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 3831cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 3841cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 3851cb0ef41Sopenharmony_ci if (-rt.immediate() >> 16 == 0 && !MustUseReg(rt.rmode())) { 3861cb0ef41Sopenharmony_ci // Use load -imm and addu when loading -imm generates one instruction. 3871cb0ef41Sopenharmony_ci li(scratch, -rt.immediate()); 3881cb0ef41Sopenharmony_ci addu(rd, rs, scratch); 3891cb0ef41Sopenharmony_ci } else { 3901cb0ef41Sopenharmony_ci // li handles the relocation. 3911cb0ef41Sopenharmony_ci li(scratch, rt); 3921cb0ef41Sopenharmony_ci subu(rd, rs, scratch); 3931cb0ef41Sopenharmony_ci } 3941cb0ef41Sopenharmony_ci } 3951cb0ef41Sopenharmony_ci } 3961cb0ef41Sopenharmony_ci} 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_civoid TurboAssembler::Dsubu(Register rd, Register rs, const Operand& rt) { 3991cb0ef41Sopenharmony_ci if (rt.is_reg()) { 4001cb0ef41Sopenharmony_ci dsubu(rd, rs, rt.rm()); 4011cb0ef41Sopenharmony_ci } else if (is_int16(-rt.immediate()) && !MustUseReg(rt.rmode())) { 4021cb0ef41Sopenharmony_ci daddiu(rd, rs, 4031cb0ef41Sopenharmony_ci static_cast<int32_t>( 4041cb0ef41Sopenharmony_ci -rt.immediate())); // No dsubiu instr, use daddiu(x, y, -imm). 4051cb0ef41Sopenharmony_ci } else { 4061cb0ef41Sopenharmony_ci DCHECK(rs != at); 4071cb0ef41Sopenharmony_ci int li_count = InstrCountForLi64Bit(rt.immediate()); 4081cb0ef41Sopenharmony_ci int li_neg_count = InstrCountForLi64Bit(-rt.immediate()); 4091cb0ef41Sopenharmony_ci if (li_neg_count < li_count && !MustUseReg(rt.rmode())) { 4101cb0ef41Sopenharmony_ci // Use load -imm and daddu when loading -imm generates one instruction. 4111cb0ef41Sopenharmony_ci DCHECK(rt.immediate() != std::numeric_limits<int32_t>::min()); 4121cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 4131cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 4141cb0ef41Sopenharmony_ci li(scratch, Operand(-rt.immediate())); 4151cb0ef41Sopenharmony_ci Daddu(rd, rs, scratch); 4161cb0ef41Sopenharmony_ci } else { 4171cb0ef41Sopenharmony_ci // li handles the relocation. 4181cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 4191cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 4201cb0ef41Sopenharmony_ci li(scratch, rt); 4211cb0ef41Sopenharmony_ci dsubu(rd, rs, scratch); 4221cb0ef41Sopenharmony_ci } 4231cb0ef41Sopenharmony_ci } 4241cb0ef41Sopenharmony_ci} 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_civoid TurboAssembler::Mul(Register rd, Register rs, const Operand& rt) { 4271cb0ef41Sopenharmony_ci if (rt.is_reg()) { 4281cb0ef41Sopenharmony_ci mul(rd, rs, rt.rm()); 4291cb0ef41Sopenharmony_ci } else { 4301cb0ef41Sopenharmony_ci // li handles the relocation. 4311cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 4321cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 4331cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 4341cb0ef41Sopenharmony_ci li(scratch, rt); 4351cb0ef41Sopenharmony_ci mul(rd, rs, scratch); 4361cb0ef41Sopenharmony_ci } 4371cb0ef41Sopenharmony_ci} 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_civoid TurboAssembler::Mulh(Register rd, Register rs, const Operand& rt) { 4401cb0ef41Sopenharmony_ci if (rt.is_reg()) { 4411cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 4421cb0ef41Sopenharmony_ci mult(rs, rt.rm()); 4431cb0ef41Sopenharmony_ci mfhi(rd); 4441cb0ef41Sopenharmony_ci } else { 4451cb0ef41Sopenharmony_ci muh(rd, rs, rt.rm()); 4461cb0ef41Sopenharmony_ci } 4471cb0ef41Sopenharmony_ci } else { 4481cb0ef41Sopenharmony_ci // li handles the relocation. 4491cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 4501cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 4511cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 4521cb0ef41Sopenharmony_ci li(scratch, rt); 4531cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 4541cb0ef41Sopenharmony_ci mult(rs, scratch); 4551cb0ef41Sopenharmony_ci mfhi(rd); 4561cb0ef41Sopenharmony_ci } else { 4571cb0ef41Sopenharmony_ci muh(rd, rs, scratch); 4581cb0ef41Sopenharmony_ci } 4591cb0ef41Sopenharmony_ci } 4601cb0ef41Sopenharmony_ci} 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_civoid TurboAssembler::Mulhu(Register rd, Register rs, const Operand& rt) { 4631cb0ef41Sopenharmony_ci if (rt.is_reg()) { 4641cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 4651cb0ef41Sopenharmony_ci multu(rs, rt.rm()); 4661cb0ef41Sopenharmony_ci mfhi(rd); 4671cb0ef41Sopenharmony_ci } else { 4681cb0ef41Sopenharmony_ci muhu(rd, rs, rt.rm()); 4691cb0ef41Sopenharmony_ci } 4701cb0ef41Sopenharmony_ci } else { 4711cb0ef41Sopenharmony_ci // li handles the relocation. 4721cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 4731cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 4741cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 4751cb0ef41Sopenharmony_ci li(scratch, rt); 4761cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 4771cb0ef41Sopenharmony_ci multu(rs, scratch); 4781cb0ef41Sopenharmony_ci mfhi(rd); 4791cb0ef41Sopenharmony_ci } else { 4801cb0ef41Sopenharmony_ci muhu(rd, rs, scratch); 4811cb0ef41Sopenharmony_ci } 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci} 4841cb0ef41Sopenharmony_ci 4851cb0ef41Sopenharmony_civoid TurboAssembler::Dmul(Register rd, Register rs, const Operand& rt) { 4861cb0ef41Sopenharmony_ci if (rt.is_reg()) { 4871cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 4881cb0ef41Sopenharmony_ci dmul(rd, rs, rt.rm()); 4891cb0ef41Sopenharmony_ci } else { 4901cb0ef41Sopenharmony_ci dmult(rs, rt.rm()); 4911cb0ef41Sopenharmony_ci mflo(rd); 4921cb0ef41Sopenharmony_ci } 4931cb0ef41Sopenharmony_ci } else { 4941cb0ef41Sopenharmony_ci // li handles the relocation. 4951cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 4961cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 4971cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 4981cb0ef41Sopenharmony_ci li(scratch, rt); 4991cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 5001cb0ef41Sopenharmony_ci dmul(rd, rs, scratch); 5011cb0ef41Sopenharmony_ci } else { 5021cb0ef41Sopenharmony_ci dmult(rs, scratch); 5031cb0ef41Sopenharmony_ci mflo(rd); 5041cb0ef41Sopenharmony_ci } 5051cb0ef41Sopenharmony_ci } 5061cb0ef41Sopenharmony_ci} 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_civoid TurboAssembler::Dmulh(Register rd, Register rs, const Operand& rt) { 5091cb0ef41Sopenharmony_ci if (rt.is_reg()) { 5101cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 5111cb0ef41Sopenharmony_ci dmuh(rd, rs, rt.rm()); 5121cb0ef41Sopenharmony_ci } else { 5131cb0ef41Sopenharmony_ci dmult(rs, rt.rm()); 5141cb0ef41Sopenharmony_ci mfhi(rd); 5151cb0ef41Sopenharmony_ci } 5161cb0ef41Sopenharmony_ci } else { 5171cb0ef41Sopenharmony_ci // li handles the relocation. 5181cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 5191cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 5201cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 5211cb0ef41Sopenharmony_ci li(scratch, rt); 5221cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 5231cb0ef41Sopenharmony_ci dmuh(rd, rs, scratch); 5241cb0ef41Sopenharmony_ci } else { 5251cb0ef41Sopenharmony_ci dmult(rs, scratch); 5261cb0ef41Sopenharmony_ci mfhi(rd); 5271cb0ef41Sopenharmony_ci } 5281cb0ef41Sopenharmony_ci } 5291cb0ef41Sopenharmony_ci} 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_civoid TurboAssembler::Mult(Register rs, const Operand& rt) { 5321cb0ef41Sopenharmony_ci if (rt.is_reg()) { 5331cb0ef41Sopenharmony_ci mult(rs, rt.rm()); 5341cb0ef41Sopenharmony_ci } else { 5351cb0ef41Sopenharmony_ci // li handles the relocation. 5361cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 5371cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 5381cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 5391cb0ef41Sopenharmony_ci li(scratch, rt); 5401cb0ef41Sopenharmony_ci mult(rs, scratch); 5411cb0ef41Sopenharmony_ci } 5421cb0ef41Sopenharmony_ci} 5431cb0ef41Sopenharmony_ci 5441cb0ef41Sopenharmony_civoid TurboAssembler::Dmult(Register rs, const Operand& rt) { 5451cb0ef41Sopenharmony_ci if (rt.is_reg()) { 5461cb0ef41Sopenharmony_ci dmult(rs, rt.rm()); 5471cb0ef41Sopenharmony_ci } else { 5481cb0ef41Sopenharmony_ci // li handles the relocation. 5491cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 5501cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 5511cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 5521cb0ef41Sopenharmony_ci li(scratch, rt); 5531cb0ef41Sopenharmony_ci dmult(rs, scratch); 5541cb0ef41Sopenharmony_ci } 5551cb0ef41Sopenharmony_ci} 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_civoid TurboAssembler::Multu(Register rs, const Operand& rt) { 5581cb0ef41Sopenharmony_ci if (rt.is_reg()) { 5591cb0ef41Sopenharmony_ci multu(rs, rt.rm()); 5601cb0ef41Sopenharmony_ci } else { 5611cb0ef41Sopenharmony_ci // li handles the relocation. 5621cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 5631cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 5641cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 5651cb0ef41Sopenharmony_ci li(scratch, rt); 5661cb0ef41Sopenharmony_ci multu(rs, scratch); 5671cb0ef41Sopenharmony_ci } 5681cb0ef41Sopenharmony_ci} 5691cb0ef41Sopenharmony_ci 5701cb0ef41Sopenharmony_civoid TurboAssembler::Dmultu(Register rs, const Operand& rt) { 5711cb0ef41Sopenharmony_ci if (rt.is_reg()) { 5721cb0ef41Sopenharmony_ci dmultu(rs, rt.rm()); 5731cb0ef41Sopenharmony_ci } else { 5741cb0ef41Sopenharmony_ci // li handles the relocation. 5751cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 5761cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 5771cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 5781cb0ef41Sopenharmony_ci li(scratch, rt); 5791cb0ef41Sopenharmony_ci dmultu(rs, scratch); 5801cb0ef41Sopenharmony_ci } 5811cb0ef41Sopenharmony_ci} 5821cb0ef41Sopenharmony_ci 5831cb0ef41Sopenharmony_civoid TurboAssembler::Div(Register rs, const Operand& rt) { 5841cb0ef41Sopenharmony_ci if (rt.is_reg()) { 5851cb0ef41Sopenharmony_ci div(rs, rt.rm()); 5861cb0ef41Sopenharmony_ci } else { 5871cb0ef41Sopenharmony_ci // li handles the relocation. 5881cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 5891cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 5901cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 5911cb0ef41Sopenharmony_ci li(scratch, rt); 5921cb0ef41Sopenharmony_ci div(rs, scratch); 5931cb0ef41Sopenharmony_ci } 5941cb0ef41Sopenharmony_ci} 5951cb0ef41Sopenharmony_ci 5961cb0ef41Sopenharmony_civoid TurboAssembler::Div(Register res, Register rs, const Operand& rt) { 5971cb0ef41Sopenharmony_ci if (rt.is_reg()) { 5981cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 5991cb0ef41Sopenharmony_ci div(rs, rt.rm()); 6001cb0ef41Sopenharmony_ci mflo(res); 6011cb0ef41Sopenharmony_ci } else { 6021cb0ef41Sopenharmony_ci div(res, rs, rt.rm()); 6031cb0ef41Sopenharmony_ci } 6041cb0ef41Sopenharmony_ci } else { 6051cb0ef41Sopenharmony_ci // li handles the relocation. 6061cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 6071cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 6081cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 6091cb0ef41Sopenharmony_ci li(scratch, rt); 6101cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 6111cb0ef41Sopenharmony_ci div(rs, scratch); 6121cb0ef41Sopenharmony_ci mflo(res); 6131cb0ef41Sopenharmony_ci } else { 6141cb0ef41Sopenharmony_ci div(res, rs, scratch); 6151cb0ef41Sopenharmony_ci } 6161cb0ef41Sopenharmony_ci } 6171cb0ef41Sopenharmony_ci} 6181cb0ef41Sopenharmony_ci 6191cb0ef41Sopenharmony_civoid TurboAssembler::Mod(Register rd, Register rs, const Operand& rt) { 6201cb0ef41Sopenharmony_ci if (rt.is_reg()) { 6211cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 6221cb0ef41Sopenharmony_ci div(rs, rt.rm()); 6231cb0ef41Sopenharmony_ci mfhi(rd); 6241cb0ef41Sopenharmony_ci } else { 6251cb0ef41Sopenharmony_ci mod(rd, rs, rt.rm()); 6261cb0ef41Sopenharmony_ci } 6271cb0ef41Sopenharmony_ci } else { 6281cb0ef41Sopenharmony_ci // li handles the relocation. 6291cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 6301cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 6311cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 6321cb0ef41Sopenharmony_ci li(scratch, rt); 6331cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 6341cb0ef41Sopenharmony_ci div(rs, scratch); 6351cb0ef41Sopenharmony_ci mfhi(rd); 6361cb0ef41Sopenharmony_ci } else { 6371cb0ef41Sopenharmony_ci mod(rd, rs, scratch); 6381cb0ef41Sopenharmony_ci } 6391cb0ef41Sopenharmony_ci } 6401cb0ef41Sopenharmony_ci} 6411cb0ef41Sopenharmony_ci 6421cb0ef41Sopenharmony_civoid TurboAssembler::Modu(Register rd, Register rs, const Operand& rt) { 6431cb0ef41Sopenharmony_ci if (rt.is_reg()) { 6441cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 6451cb0ef41Sopenharmony_ci divu(rs, rt.rm()); 6461cb0ef41Sopenharmony_ci mfhi(rd); 6471cb0ef41Sopenharmony_ci } else { 6481cb0ef41Sopenharmony_ci modu(rd, rs, rt.rm()); 6491cb0ef41Sopenharmony_ci } 6501cb0ef41Sopenharmony_ci } else { 6511cb0ef41Sopenharmony_ci // li handles the relocation. 6521cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 6531cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 6541cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 6551cb0ef41Sopenharmony_ci li(scratch, rt); 6561cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 6571cb0ef41Sopenharmony_ci divu(rs, scratch); 6581cb0ef41Sopenharmony_ci mfhi(rd); 6591cb0ef41Sopenharmony_ci } else { 6601cb0ef41Sopenharmony_ci modu(rd, rs, scratch); 6611cb0ef41Sopenharmony_ci } 6621cb0ef41Sopenharmony_ci } 6631cb0ef41Sopenharmony_ci} 6641cb0ef41Sopenharmony_ci 6651cb0ef41Sopenharmony_civoid TurboAssembler::Ddiv(Register rs, const Operand& rt) { 6661cb0ef41Sopenharmony_ci if (rt.is_reg()) { 6671cb0ef41Sopenharmony_ci ddiv(rs, rt.rm()); 6681cb0ef41Sopenharmony_ci } else { 6691cb0ef41Sopenharmony_ci // li handles the relocation. 6701cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 6711cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 6721cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 6731cb0ef41Sopenharmony_ci li(scratch, rt); 6741cb0ef41Sopenharmony_ci ddiv(rs, scratch); 6751cb0ef41Sopenharmony_ci } 6761cb0ef41Sopenharmony_ci} 6771cb0ef41Sopenharmony_ci 6781cb0ef41Sopenharmony_civoid TurboAssembler::Ddiv(Register rd, Register rs, const Operand& rt) { 6791cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 6801cb0ef41Sopenharmony_ci if (rt.is_reg()) { 6811cb0ef41Sopenharmony_ci ddiv(rs, rt.rm()); 6821cb0ef41Sopenharmony_ci mflo(rd); 6831cb0ef41Sopenharmony_ci } else { 6841cb0ef41Sopenharmony_ci // li handles the relocation. 6851cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 6861cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 6871cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 6881cb0ef41Sopenharmony_ci li(scratch, rt); 6891cb0ef41Sopenharmony_ci ddiv(rs, scratch); 6901cb0ef41Sopenharmony_ci mflo(rd); 6911cb0ef41Sopenharmony_ci } 6921cb0ef41Sopenharmony_ci } else { 6931cb0ef41Sopenharmony_ci if (rt.is_reg()) { 6941cb0ef41Sopenharmony_ci ddiv(rd, rs, rt.rm()); 6951cb0ef41Sopenharmony_ci } else { 6961cb0ef41Sopenharmony_ci // li handles the relocation. 6971cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 6981cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 6991cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 7001cb0ef41Sopenharmony_ci li(scratch, rt); 7011cb0ef41Sopenharmony_ci ddiv(rd, rs, scratch); 7021cb0ef41Sopenharmony_ci } 7031cb0ef41Sopenharmony_ci } 7041cb0ef41Sopenharmony_ci} 7051cb0ef41Sopenharmony_ci 7061cb0ef41Sopenharmony_civoid TurboAssembler::Divu(Register rs, const Operand& rt) { 7071cb0ef41Sopenharmony_ci if (rt.is_reg()) { 7081cb0ef41Sopenharmony_ci divu(rs, rt.rm()); 7091cb0ef41Sopenharmony_ci } else { 7101cb0ef41Sopenharmony_ci // li handles the relocation. 7111cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 7121cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 7131cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 7141cb0ef41Sopenharmony_ci li(scratch, rt); 7151cb0ef41Sopenharmony_ci divu(rs, scratch); 7161cb0ef41Sopenharmony_ci } 7171cb0ef41Sopenharmony_ci} 7181cb0ef41Sopenharmony_ci 7191cb0ef41Sopenharmony_civoid TurboAssembler::Divu(Register res, Register rs, const Operand& rt) { 7201cb0ef41Sopenharmony_ci if (rt.is_reg()) { 7211cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 7221cb0ef41Sopenharmony_ci divu(rs, rt.rm()); 7231cb0ef41Sopenharmony_ci mflo(res); 7241cb0ef41Sopenharmony_ci } else { 7251cb0ef41Sopenharmony_ci divu(res, rs, rt.rm()); 7261cb0ef41Sopenharmony_ci } 7271cb0ef41Sopenharmony_ci } else { 7281cb0ef41Sopenharmony_ci // li handles the relocation. 7291cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 7301cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 7311cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 7321cb0ef41Sopenharmony_ci li(scratch, rt); 7331cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 7341cb0ef41Sopenharmony_ci divu(rs, scratch); 7351cb0ef41Sopenharmony_ci mflo(res); 7361cb0ef41Sopenharmony_ci } else { 7371cb0ef41Sopenharmony_ci divu(res, rs, scratch); 7381cb0ef41Sopenharmony_ci } 7391cb0ef41Sopenharmony_ci } 7401cb0ef41Sopenharmony_ci} 7411cb0ef41Sopenharmony_ci 7421cb0ef41Sopenharmony_civoid TurboAssembler::Ddivu(Register rs, const Operand& rt) { 7431cb0ef41Sopenharmony_ci if (rt.is_reg()) { 7441cb0ef41Sopenharmony_ci ddivu(rs, rt.rm()); 7451cb0ef41Sopenharmony_ci } else { 7461cb0ef41Sopenharmony_ci // li handles the relocation. 7471cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 7481cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 7491cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 7501cb0ef41Sopenharmony_ci li(scratch, rt); 7511cb0ef41Sopenharmony_ci ddivu(rs, scratch); 7521cb0ef41Sopenharmony_ci } 7531cb0ef41Sopenharmony_ci} 7541cb0ef41Sopenharmony_ci 7551cb0ef41Sopenharmony_civoid TurboAssembler::Ddivu(Register res, Register rs, const Operand& rt) { 7561cb0ef41Sopenharmony_ci if (rt.is_reg()) { 7571cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 7581cb0ef41Sopenharmony_ci ddivu(rs, rt.rm()); 7591cb0ef41Sopenharmony_ci mflo(res); 7601cb0ef41Sopenharmony_ci } else { 7611cb0ef41Sopenharmony_ci ddivu(res, rs, rt.rm()); 7621cb0ef41Sopenharmony_ci } 7631cb0ef41Sopenharmony_ci } else { 7641cb0ef41Sopenharmony_ci // li handles the relocation. 7651cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 7661cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 7671cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 7681cb0ef41Sopenharmony_ci li(scratch, rt); 7691cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 7701cb0ef41Sopenharmony_ci ddivu(rs, scratch); 7711cb0ef41Sopenharmony_ci mflo(res); 7721cb0ef41Sopenharmony_ci } else { 7731cb0ef41Sopenharmony_ci ddivu(res, rs, scratch); 7741cb0ef41Sopenharmony_ci } 7751cb0ef41Sopenharmony_ci } 7761cb0ef41Sopenharmony_ci} 7771cb0ef41Sopenharmony_ci 7781cb0ef41Sopenharmony_civoid TurboAssembler::Dmod(Register rd, Register rs, const Operand& rt) { 7791cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 7801cb0ef41Sopenharmony_ci if (rt.is_reg()) { 7811cb0ef41Sopenharmony_ci ddiv(rs, rt.rm()); 7821cb0ef41Sopenharmony_ci mfhi(rd); 7831cb0ef41Sopenharmony_ci } else { 7841cb0ef41Sopenharmony_ci // li handles the relocation. 7851cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 7861cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 7871cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 7881cb0ef41Sopenharmony_ci li(scratch, rt); 7891cb0ef41Sopenharmony_ci ddiv(rs, scratch); 7901cb0ef41Sopenharmony_ci mfhi(rd); 7911cb0ef41Sopenharmony_ci } 7921cb0ef41Sopenharmony_ci } else { 7931cb0ef41Sopenharmony_ci if (rt.is_reg()) { 7941cb0ef41Sopenharmony_ci dmod(rd, rs, rt.rm()); 7951cb0ef41Sopenharmony_ci } else { 7961cb0ef41Sopenharmony_ci // li handles the relocation. 7971cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 7981cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 7991cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 8001cb0ef41Sopenharmony_ci li(scratch, rt); 8011cb0ef41Sopenharmony_ci dmod(rd, rs, scratch); 8021cb0ef41Sopenharmony_ci } 8031cb0ef41Sopenharmony_ci } 8041cb0ef41Sopenharmony_ci} 8051cb0ef41Sopenharmony_ci 8061cb0ef41Sopenharmony_civoid TurboAssembler::Dmodu(Register rd, Register rs, const Operand& rt) { 8071cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 8081cb0ef41Sopenharmony_ci if (rt.is_reg()) { 8091cb0ef41Sopenharmony_ci ddivu(rs, rt.rm()); 8101cb0ef41Sopenharmony_ci mfhi(rd); 8111cb0ef41Sopenharmony_ci } else { 8121cb0ef41Sopenharmony_ci // li handles the relocation. 8131cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 8141cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 8151cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 8161cb0ef41Sopenharmony_ci li(scratch, rt); 8171cb0ef41Sopenharmony_ci ddivu(rs, scratch); 8181cb0ef41Sopenharmony_ci mfhi(rd); 8191cb0ef41Sopenharmony_ci } 8201cb0ef41Sopenharmony_ci } else { 8211cb0ef41Sopenharmony_ci if (rt.is_reg()) { 8221cb0ef41Sopenharmony_ci dmodu(rd, rs, rt.rm()); 8231cb0ef41Sopenharmony_ci } else { 8241cb0ef41Sopenharmony_ci // li handles the relocation. 8251cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 8261cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 8271cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 8281cb0ef41Sopenharmony_ci li(scratch, rt); 8291cb0ef41Sopenharmony_ci dmodu(rd, rs, scratch); 8301cb0ef41Sopenharmony_ci } 8311cb0ef41Sopenharmony_ci } 8321cb0ef41Sopenharmony_ci} 8331cb0ef41Sopenharmony_ci 8341cb0ef41Sopenharmony_civoid TurboAssembler::And(Register rd, Register rs, const Operand& rt) { 8351cb0ef41Sopenharmony_ci if (rt.is_reg()) { 8361cb0ef41Sopenharmony_ci and_(rd, rs, rt.rm()); 8371cb0ef41Sopenharmony_ci } else { 8381cb0ef41Sopenharmony_ci if (is_uint16(rt.immediate()) && !MustUseReg(rt.rmode())) { 8391cb0ef41Sopenharmony_ci andi(rd, rs, static_cast<int32_t>(rt.immediate())); 8401cb0ef41Sopenharmony_ci } else { 8411cb0ef41Sopenharmony_ci // li handles the relocation. 8421cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 8431cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 8441cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 8451cb0ef41Sopenharmony_ci li(scratch, rt); 8461cb0ef41Sopenharmony_ci and_(rd, rs, scratch); 8471cb0ef41Sopenharmony_ci } 8481cb0ef41Sopenharmony_ci } 8491cb0ef41Sopenharmony_ci} 8501cb0ef41Sopenharmony_ci 8511cb0ef41Sopenharmony_civoid TurboAssembler::Or(Register rd, Register rs, const Operand& rt) { 8521cb0ef41Sopenharmony_ci if (rt.is_reg()) { 8531cb0ef41Sopenharmony_ci or_(rd, rs, rt.rm()); 8541cb0ef41Sopenharmony_ci } else { 8551cb0ef41Sopenharmony_ci if (is_uint16(rt.immediate()) && !MustUseReg(rt.rmode())) { 8561cb0ef41Sopenharmony_ci ori(rd, rs, static_cast<int32_t>(rt.immediate())); 8571cb0ef41Sopenharmony_ci } else { 8581cb0ef41Sopenharmony_ci // li handles the relocation. 8591cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 8601cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 8611cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 8621cb0ef41Sopenharmony_ci li(scratch, rt); 8631cb0ef41Sopenharmony_ci or_(rd, rs, scratch); 8641cb0ef41Sopenharmony_ci } 8651cb0ef41Sopenharmony_ci } 8661cb0ef41Sopenharmony_ci} 8671cb0ef41Sopenharmony_ci 8681cb0ef41Sopenharmony_civoid TurboAssembler::Xor(Register rd, Register rs, const Operand& rt) { 8691cb0ef41Sopenharmony_ci if (rt.is_reg()) { 8701cb0ef41Sopenharmony_ci xor_(rd, rs, rt.rm()); 8711cb0ef41Sopenharmony_ci } else { 8721cb0ef41Sopenharmony_ci if (is_uint16(rt.immediate()) && !MustUseReg(rt.rmode())) { 8731cb0ef41Sopenharmony_ci xori(rd, rs, static_cast<int32_t>(rt.immediate())); 8741cb0ef41Sopenharmony_ci } else { 8751cb0ef41Sopenharmony_ci // li handles the relocation. 8761cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 8771cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 8781cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 8791cb0ef41Sopenharmony_ci li(scratch, rt); 8801cb0ef41Sopenharmony_ci xor_(rd, rs, scratch); 8811cb0ef41Sopenharmony_ci } 8821cb0ef41Sopenharmony_ci } 8831cb0ef41Sopenharmony_ci} 8841cb0ef41Sopenharmony_ci 8851cb0ef41Sopenharmony_civoid TurboAssembler::Nor(Register rd, Register rs, const Operand& rt) { 8861cb0ef41Sopenharmony_ci if (rt.is_reg()) { 8871cb0ef41Sopenharmony_ci nor(rd, rs, rt.rm()); 8881cb0ef41Sopenharmony_ci } else { 8891cb0ef41Sopenharmony_ci // li handles the relocation. 8901cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 8911cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 8921cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 8931cb0ef41Sopenharmony_ci li(scratch, rt); 8941cb0ef41Sopenharmony_ci nor(rd, rs, scratch); 8951cb0ef41Sopenharmony_ci } 8961cb0ef41Sopenharmony_ci} 8971cb0ef41Sopenharmony_ci 8981cb0ef41Sopenharmony_civoid TurboAssembler::Neg(Register rs, const Operand& rt) { 8991cb0ef41Sopenharmony_ci dsubu(rs, zero_reg, rt.rm()); 9001cb0ef41Sopenharmony_ci} 9011cb0ef41Sopenharmony_ci 9021cb0ef41Sopenharmony_civoid TurboAssembler::Slt(Register rd, Register rs, const Operand& rt) { 9031cb0ef41Sopenharmony_ci if (rt.is_reg()) { 9041cb0ef41Sopenharmony_ci slt(rd, rs, rt.rm()); 9051cb0ef41Sopenharmony_ci } else { 9061cb0ef41Sopenharmony_ci if (is_int16(rt.immediate()) && !MustUseReg(rt.rmode())) { 9071cb0ef41Sopenharmony_ci slti(rd, rs, static_cast<int32_t>(rt.immediate())); 9081cb0ef41Sopenharmony_ci } else { 9091cb0ef41Sopenharmony_ci // li handles the relocation. 9101cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 9111cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 9121cb0ef41Sopenharmony_ci Register scratch = temps.hasAvailable() ? temps.Acquire() : t8; 9131cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 9141cb0ef41Sopenharmony_ci li(scratch, rt); 9151cb0ef41Sopenharmony_ci slt(rd, rs, scratch); 9161cb0ef41Sopenharmony_ci } 9171cb0ef41Sopenharmony_ci } 9181cb0ef41Sopenharmony_ci} 9191cb0ef41Sopenharmony_ci 9201cb0ef41Sopenharmony_civoid TurboAssembler::Sltu(Register rd, Register rs, const Operand& rt) { 9211cb0ef41Sopenharmony_ci if (rt.is_reg()) { 9221cb0ef41Sopenharmony_ci sltu(rd, rs, rt.rm()); 9231cb0ef41Sopenharmony_ci } else { 9241cb0ef41Sopenharmony_ci const uint64_t int16_min = std::numeric_limits<int16_t>::min(); 9251cb0ef41Sopenharmony_ci if (is_uint15(rt.immediate()) && !MustUseReg(rt.rmode())) { 9261cb0ef41Sopenharmony_ci // Imm range is: [0, 32767]. 9271cb0ef41Sopenharmony_ci sltiu(rd, rs, static_cast<int32_t>(rt.immediate())); 9281cb0ef41Sopenharmony_ci } else if (is_uint15(rt.immediate() - int16_min) && 9291cb0ef41Sopenharmony_ci !MustUseReg(rt.rmode())) { 9301cb0ef41Sopenharmony_ci // Imm range is: [max_unsigned-32767,max_unsigned]. 9311cb0ef41Sopenharmony_ci sltiu(rd, rs, static_cast<uint16_t>(rt.immediate())); 9321cb0ef41Sopenharmony_ci } else { 9331cb0ef41Sopenharmony_ci // li handles the relocation. 9341cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 9351cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 9361cb0ef41Sopenharmony_ci Register scratch = temps.hasAvailable() ? temps.Acquire() : t8; 9371cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 9381cb0ef41Sopenharmony_ci li(scratch, rt); 9391cb0ef41Sopenharmony_ci sltu(rd, rs, scratch); 9401cb0ef41Sopenharmony_ci } 9411cb0ef41Sopenharmony_ci } 9421cb0ef41Sopenharmony_ci} 9431cb0ef41Sopenharmony_ci 9441cb0ef41Sopenharmony_civoid TurboAssembler::Sle(Register rd, Register rs, const Operand& rt) { 9451cb0ef41Sopenharmony_ci if (rt.is_reg()) { 9461cb0ef41Sopenharmony_ci slt(rd, rt.rm(), rs); 9471cb0ef41Sopenharmony_ci } else { 9481cb0ef41Sopenharmony_ci // li handles the relocation. 9491cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 9501cb0ef41Sopenharmony_ci Register scratch = temps.hasAvailable() ? temps.Acquire() : t8; 9511cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 9521cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 9531cb0ef41Sopenharmony_ci li(scratch, rt); 9541cb0ef41Sopenharmony_ci slt(rd, scratch, rs); 9551cb0ef41Sopenharmony_ci } 9561cb0ef41Sopenharmony_ci xori(rd, rd, 1); 9571cb0ef41Sopenharmony_ci} 9581cb0ef41Sopenharmony_ci 9591cb0ef41Sopenharmony_civoid TurboAssembler::Sleu(Register rd, Register rs, const Operand& rt) { 9601cb0ef41Sopenharmony_ci if (rt.is_reg()) { 9611cb0ef41Sopenharmony_ci sltu(rd, rt.rm(), rs); 9621cb0ef41Sopenharmony_ci } else { 9631cb0ef41Sopenharmony_ci // li handles the relocation. 9641cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 9651cb0ef41Sopenharmony_ci Register scratch = temps.hasAvailable() ? temps.Acquire() : t8; 9661cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 9671cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 9681cb0ef41Sopenharmony_ci li(scratch, rt); 9691cb0ef41Sopenharmony_ci sltu(rd, scratch, rs); 9701cb0ef41Sopenharmony_ci } 9711cb0ef41Sopenharmony_ci xori(rd, rd, 1); 9721cb0ef41Sopenharmony_ci} 9731cb0ef41Sopenharmony_ci 9741cb0ef41Sopenharmony_civoid TurboAssembler::Sge(Register rd, Register rs, const Operand& rt) { 9751cb0ef41Sopenharmony_ci Slt(rd, rs, rt); 9761cb0ef41Sopenharmony_ci xori(rd, rd, 1); 9771cb0ef41Sopenharmony_ci} 9781cb0ef41Sopenharmony_ci 9791cb0ef41Sopenharmony_civoid TurboAssembler::Sgeu(Register rd, Register rs, const Operand& rt) { 9801cb0ef41Sopenharmony_ci Sltu(rd, rs, rt); 9811cb0ef41Sopenharmony_ci xori(rd, rd, 1); 9821cb0ef41Sopenharmony_ci} 9831cb0ef41Sopenharmony_ci 9841cb0ef41Sopenharmony_civoid TurboAssembler::Sgt(Register rd, Register rs, const Operand& rt) { 9851cb0ef41Sopenharmony_ci if (rt.is_reg()) { 9861cb0ef41Sopenharmony_ci slt(rd, rt.rm(), rs); 9871cb0ef41Sopenharmony_ci } else { 9881cb0ef41Sopenharmony_ci // li handles the relocation. 9891cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 9901cb0ef41Sopenharmony_ci Register scratch = temps.hasAvailable() ? temps.Acquire() : t8; 9911cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 9921cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 9931cb0ef41Sopenharmony_ci li(scratch, rt); 9941cb0ef41Sopenharmony_ci slt(rd, scratch, rs); 9951cb0ef41Sopenharmony_ci } 9961cb0ef41Sopenharmony_ci} 9971cb0ef41Sopenharmony_ci 9981cb0ef41Sopenharmony_civoid TurboAssembler::Sgtu(Register rd, Register rs, const Operand& rt) { 9991cb0ef41Sopenharmony_ci if (rt.is_reg()) { 10001cb0ef41Sopenharmony_ci sltu(rd, rt.rm(), rs); 10011cb0ef41Sopenharmony_ci } else { 10021cb0ef41Sopenharmony_ci // li handles the relocation. 10031cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 10041cb0ef41Sopenharmony_ci Register scratch = temps.hasAvailable() ? temps.Acquire() : t8; 10051cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 10061cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 10071cb0ef41Sopenharmony_ci li(scratch, rt); 10081cb0ef41Sopenharmony_ci sltu(rd, scratch, rs); 10091cb0ef41Sopenharmony_ci } 10101cb0ef41Sopenharmony_ci} 10111cb0ef41Sopenharmony_ci 10121cb0ef41Sopenharmony_civoid TurboAssembler::Ror(Register rd, Register rs, const Operand& rt) { 10131cb0ef41Sopenharmony_ci if (rt.is_reg()) { 10141cb0ef41Sopenharmony_ci rotrv(rd, rs, rt.rm()); 10151cb0ef41Sopenharmony_ci } else { 10161cb0ef41Sopenharmony_ci int64_t ror_value = rt.immediate() % 32; 10171cb0ef41Sopenharmony_ci if (ror_value < 0) { 10181cb0ef41Sopenharmony_ci ror_value += 32; 10191cb0ef41Sopenharmony_ci } 10201cb0ef41Sopenharmony_ci rotr(rd, rs, ror_value); 10211cb0ef41Sopenharmony_ci } 10221cb0ef41Sopenharmony_ci} 10231cb0ef41Sopenharmony_ci 10241cb0ef41Sopenharmony_civoid TurboAssembler::Dror(Register rd, Register rs, const Operand& rt) { 10251cb0ef41Sopenharmony_ci if (rt.is_reg()) { 10261cb0ef41Sopenharmony_ci drotrv(rd, rs, rt.rm()); 10271cb0ef41Sopenharmony_ci } else { 10281cb0ef41Sopenharmony_ci int64_t dror_value = rt.immediate() % 64; 10291cb0ef41Sopenharmony_ci if (dror_value < 0) dror_value += 64; 10301cb0ef41Sopenharmony_ci if (dror_value <= 31) { 10311cb0ef41Sopenharmony_ci drotr(rd, rs, dror_value); 10321cb0ef41Sopenharmony_ci } else { 10331cb0ef41Sopenharmony_ci drotr32(rd, rs, dror_value - 32); 10341cb0ef41Sopenharmony_ci } 10351cb0ef41Sopenharmony_ci } 10361cb0ef41Sopenharmony_ci} 10371cb0ef41Sopenharmony_ci 10381cb0ef41Sopenharmony_civoid MacroAssembler::Pref(int32_t hint, const MemOperand& rs) { 10391cb0ef41Sopenharmony_ci pref(hint, rs); 10401cb0ef41Sopenharmony_ci} 10411cb0ef41Sopenharmony_ci 10421cb0ef41Sopenharmony_civoid TurboAssembler::Lsa(Register rd, Register rt, Register rs, uint8_t sa, 10431cb0ef41Sopenharmony_ci Register scratch) { 10441cb0ef41Sopenharmony_ci DCHECK(sa >= 1 && sa <= 31); 10451cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && sa <= 4) { 10461cb0ef41Sopenharmony_ci lsa(rd, rt, rs, sa - 1); 10471cb0ef41Sopenharmony_ci } else { 10481cb0ef41Sopenharmony_ci Register tmp = rd == rt ? scratch : rd; 10491cb0ef41Sopenharmony_ci DCHECK(tmp != rt); 10501cb0ef41Sopenharmony_ci sll(tmp, rs, sa); 10511cb0ef41Sopenharmony_ci Addu(rd, rt, tmp); 10521cb0ef41Sopenharmony_ci } 10531cb0ef41Sopenharmony_ci} 10541cb0ef41Sopenharmony_ci 10551cb0ef41Sopenharmony_civoid TurboAssembler::Dlsa(Register rd, Register rt, Register rs, uint8_t sa, 10561cb0ef41Sopenharmony_ci Register scratch) { 10571cb0ef41Sopenharmony_ci DCHECK(sa >= 1 && sa <= 63); 10581cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && sa <= 4) { 10591cb0ef41Sopenharmony_ci dlsa(rd, rt, rs, sa - 1); 10601cb0ef41Sopenharmony_ci } else { 10611cb0ef41Sopenharmony_ci Register tmp = rd == rt ? scratch : rd; 10621cb0ef41Sopenharmony_ci DCHECK(tmp != rt); 10631cb0ef41Sopenharmony_ci if (sa <= 31) 10641cb0ef41Sopenharmony_ci dsll(tmp, rs, sa); 10651cb0ef41Sopenharmony_ci else 10661cb0ef41Sopenharmony_ci dsll32(tmp, rs, sa - 32); 10671cb0ef41Sopenharmony_ci Daddu(rd, rt, tmp); 10681cb0ef41Sopenharmony_ci } 10691cb0ef41Sopenharmony_ci} 10701cb0ef41Sopenharmony_ci 10711cb0ef41Sopenharmony_civoid TurboAssembler::Bovc(Register rs, Register rt, Label* L) { 10721cb0ef41Sopenharmony_ci if (is_trampoline_emitted()) { 10731cb0ef41Sopenharmony_ci Label skip; 10741cb0ef41Sopenharmony_ci bnvc(rs, rt, &skip); 10751cb0ef41Sopenharmony_ci BranchLong(L, PROTECT); 10761cb0ef41Sopenharmony_ci bind(&skip); 10771cb0ef41Sopenharmony_ci } else { 10781cb0ef41Sopenharmony_ci bovc(rs, rt, L); 10791cb0ef41Sopenharmony_ci } 10801cb0ef41Sopenharmony_ci} 10811cb0ef41Sopenharmony_ci 10821cb0ef41Sopenharmony_civoid TurboAssembler::Bnvc(Register rs, Register rt, Label* L) { 10831cb0ef41Sopenharmony_ci if (is_trampoline_emitted()) { 10841cb0ef41Sopenharmony_ci Label skip; 10851cb0ef41Sopenharmony_ci bovc(rs, rt, &skip); 10861cb0ef41Sopenharmony_ci BranchLong(L, PROTECT); 10871cb0ef41Sopenharmony_ci bind(&skip); 10881cb0ef41Sopenharmony_ci } else { 10891cb0ef41Sopenharmony_ci bnvc(rs, rt, L); 10901cb0ef41Sopenharmony_ci } 10911cb0ef41Sopenharmony_ci} 10921cb0ef41Sopenharmony_ci 10931cb0ef41Sopenharmony_ci// ------------Pseudo-instructions------------- 10941cb0ef41Sopenharmony_ci 10951cb0ef41Sopenharmony_ci// Change endianness 10961cb0ef41Sopenharmony_civoid TurboAssembler::ByteSwapSigned(Register dest, Register src, 10971cb0ef41Sopenharmony_ci int operand_size) { 10981cb0ef41Sopenharmony_ci DCHECK(operand_size == 2 || operand_size == 4 || operand_size == 8); 10991cb0ef41Sopenharmony_ci DCHECK(kArchVariant == kMips64r6 || kArchVariant == kMips64r2); 11001cb0ef41Sopenharmony_ci if (operand_size == 2) { 11011cb0ef41Sopenharmony_ci wsbh(dest, src); 11021cb0ef41Sopenharmony_ci seh(dest, dest); 11031cb0ef41Sopenharmony_ci } else if (operand_size == 4) { 11041cb0ef41Sopenharmony_ci wsbh(dest, src); 11051cb0ef41Sopenharmony_ci rotr(dest, dest, 16); 11061cb0ef41Sopenharmony_ci } else { 11071cb0ef41Sopenharmony_ci dsbh(dest, src); 11081cb0ef41Sopenharmony_ci dshd(dest, dest); 11091cb0ef41Sopenharmony_ci } 11101cb0ef41Sopenharmony_ci} 11111cb0ef41Sopenharmony_ci 11121cb0ef41Sopenharmony_civoid TurboAssembler::ByteSwapUnsigned(Register dest, Register src, 11131cb0ef41Sopenharmony_ci int operand_size) { 11141cb0ef41Sopenharmony_ci DCHECK(operand_size == 2 || operand_size == 4); 11151cb0ef41Sopenharmony_ci if (operand_size == 2) { 11161cb0ef41Sopenharmony_ci wsbh(dest, src); 11171cb0ef41Sopenharmony_ci andi(dest, dest, 0xFFFF); 11181cb0ef41Sopenharmony_ci } else { 11191cb0ef41Sopenharmony_ci wsbh(dest, src); 11201cb0ef41Sopenharmony_ci rotr(dest, dest, 16); 11211cb0ef41Sopenharmony_ci dinsu_(dest, zero_reg, 32, 32); 11221cb0ef41Sopenharmony_ci } 11231cb0ef41Sopenharmony_ci} 11241cb0ef41Sopenharmony_ci 11251cb0ef41Sopenharmony_civoid TurboAssembler::Ulw(Register rd, const MemOperand& rs) { 11261cb0ef41Sopenharmony_ci DCHECK(rd != at); 11271cb0ef41Sopenharmony_ci DCHECK(rs.rm() != at); 11281cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 11291cb0ef41Sopenharmony_ci Lw(rd, rs); 11301cb0ef41Sopenharmony_ci } else { 11311cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 11321cb0ef41Sopenharmony_ci DCHECK(kMipsLwrOffset <= 3 && kMipsLwlOffset <= 3); 11331cb0ef41Sopenharmony_ci MemOperand source = rs; 11341cb0ef41Sopenharmony_ci // Adjust offset for two accesses and check if offset + 3 fits into int16_t. 11351cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source, OffsetAccessType::TWO_ACCESSES, 3); 11361cb0ef41Sopenharmony_ci if (rd != source.rm()) { 11371cb0ef41Sopenharmony_ci lwr(rd, MemOperand(source.rm(), source.offset() + kMipsLwrOffset)); 11381cb0ef41Sopenharmony_ci lwl(rd, MemOperand(source.rm(), source.offset() + kMipsLwlOffset)); 11391cb0ef41Sopenharmony_ci } else { 11401cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 11411cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 11421cb0ef41Sopenharmony_ci lwr(scratch, MemOperand(rs.rm(), rs.offset() + kMipsLwrOffset)); 11431cb0ef41Sopenharmony_ci lwl(scratch, MemOperand(rs.rm(), rs.offset() + kMipsLwlOffset)); 11441cb0ef41Sopenharmony_ci mov(rd, scratch); 11451cb0ef41Sopenharmony_ci } 11461cb0ef41Sopenharmony_ci } 11471cb0ef41Sopenharmony_ci} 11481cb0ef41Sopenharmony_ci 11491cb0ef41Sopenharmony_civoid TurboAssembler::Ulwu(Register rd, const MemOperand& rs) { 11501cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 11511cb0ef41Sopenharmony_ci Lwu(rd, rs); 11521cb0ef41Sopenharmony_ci } else { 11531cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 11541cb0ef41Sopenharmony_ci Ulw(rd, rs); 11551cb0ef41Sopenharmony_ci Dext(rd, rd, 0, 32); 11561cb0ef41Sopenharmony_ci } 11571cb0ef41Sopenharmony_ci} 11581cb0ef41Sopenharmony_ci 11591cb0ef41Sopenharmony_civoid TurboAssembler::Usw(Register rd, const MemOperand& rs) { 11601cb0ef41Sopenharmony_ci DCHECK(rd != at); 11611cb0ef41Sopenharmony_ci DCHECK(rs.rm() != at); 11621cb0ef41Sopenharmony_ci DCHECK(rd != rs.rm()); 11631cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 11641cb0ef41Sopenharmony_ci Sw(rd, rs); 11651cb0ef41Sopenharmony_ci } else { 11661cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 11671cb0ef41Sopenharmony_ci DCHECK(kMipsSwrOffset <= 3 && kMipsSwlOffset <= 3); 11681cb0ef41Sopenharmony_ci MemOperand source = rs; 11691cb0ef41Sopenharmony_ci // Adjust offset for two accesses and check if offset + 3 fits into int16_t. 11701cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source, OffsetAccessType::TWO_ACCESSES, 3); 11711cb0ef41Sopenharmony_ci swr(rd, MemOperand(source.rm(), source.offset() + kMipsSwrOffset)); 11721cb0ef41Sopenharmony_ci swl(rd, MemOperand(source.rm(), source.offset() + kMipsSwlOffset)); 11731cb0ef41Sopenharmony_ci } 11741cb0ef41Sopenharmony_ci} 11751cb0ef41Sopenharmony_ci 11761cb0ef41Sopenharmony_civoid TurboAssembler::Ulh(Register rd, const MemOperand& rs) { 11771cb0ef41Sopenharmony_ci DCHECK(rd != at); 11781cb0ef41Sopenharmony_ci DCHECK(rs.rm() != at); 11791cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 11801cb0ef41Sopenharmony_ci Lh(rd, rs); 11811cb0ef41Sopenharmony_ci } else { 11821cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 11831cb0ef41Sopenharmony_ci MemOperand source = rs; 11841cb0ef41Sopenharmony_ci // Adjust offset for two accesses and check if offset + 1 fits into int16_t. 11851cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source, OffsetAccessType::TWO_ACCESSES, 1); 11861cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 11871cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 11881cb0ef41Sopenharmony_ci if (source.rm() == scratch) { 11891cb0ef41Sopenharmony_ci#if defined(V8_TARGET_LITTLE_ENDIAN) 11901cb0ef41Sopenharmony_ci Lb(rd, MemOperand(source.rm(), source.offset() + 1)); 11911cb0ef41Sopenharmony_ci Lbu(scratch, source); 11921cb0ef41Sopenharmony_ci#elif defined(V8_TARGET_BIG_ENDIAN) 11931cb0ef41Sopenharmony_ci Lb(rd, source); 11941cb0ef41Sopenharmony_ci Lbu(scratch, MemOperand(source.rm(), source.offset() + 1)); 11951cb0ef41Sopenharmony_ci#endif 11961cb0ef41Sopenharmony_ci } else { 11971cb0ef41Sopenharmony_ci#if defined(V8_TARGET_LITTLE_ENDIAN) 11981cb0ef41Sopenharmony_ci Lbu(scratch, source); 11991cb0ef41Sopenharmony_ci Lb(rd, MemOperand(source.rm(), source.offset() + 1)); 12001cb0ef41Sopenharmony_ci#elif defined(V8_TARGET_BIG_ENDIAN) 12011cb0ef41Sopenharmony_ci Lbu(scratch, MemOperand(source.rm(), source.offset() + 1)); 12021cb0ef41Sopenharmony_ci Lb(rd, source); 12031cb0ef41Sopenharmony_ci#endif 12041cb0ef41Sopenharmony_ci } 12051cb0ef41Sopenharmony_ci dsll(rd, rd, 8); 12061cb0ef41Sopenharmony_ci or_(rd, rd, scratch); 12071cb0ef41Sopenharmony_ci } 12081cb0ef41Sopenharmony_ci} 12091cb0ef41Sopenharmony_ci 12101cb0ef41Sopenharmony_civoid TurboAssembler::Ulhu(Register rd, const MemOperand& rs) { 12111cb0ef41Sopenharmony_ci DCHECK(rd != at); 12121cb0ef41Sopenharmony_ci DCHECK(rs.rm() != at); 12131cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 12141cb0ef41Sopenharmony_ci Lhu(rd, rs); 12151cb0ef41Sopenharmony_ci } else { 12161cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 12171cb0ef41Sopenharmony_ci MemOperand source = rs; 12181cb0ef41Sopenharmony_ci // Adjust offset for two accesses and check if offset + 1 fits into int16_t. 12191cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source, OffsetAccessType::TWO_ACCESSES, 1); 12201cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 12211cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 12221cb0ef41Sopenharmony_ci if (source.rm() == scratch) { 12231cb0ef41Sopenharmony_ci#if defined(V8_TARGET_LITTLE_ENDIAN) 12241cb0ef41Sopenharmony_ci Lbu(rd, MemOperand(source.rm(), source.offset() + 1)); 12251cb0ef41Sopenharmony_ci Lbu(scratch, source); 12261cb0ef41Sopenharmony_ci#elif defined(V8_TARGET_BIG_ENDIAN) 12271cb0ef41Sopenharmony_ci Lbu(rd, source); 12281cb0ef41Sopenharmony_ci Lbu(scratch, MemOperand(source.rm(), source.offset() + 1)); 12291cb0ef41Sopenharmony_ci#endif 12301cb0ef41Sopenharmony_ci } else { 12311cb0ef41Sopenharmony_ci#if defined(V8_TARGET_LITTLE_ENDIAN) 12321cb0ef41Sopenharmony_ci Lbu(scratch, source); 12331cb0ef41Sopenharmony_ci Lbu(rd, MemOperand(source.rm(), source.offset() + 1)); 12341cb0ef41Sopenharmony_ci#elif defined(V8_TARGET_BIG_ENDIAN) 12351cb0ef41Sopenharmony_ci Lbu(scratch, MemOperand(source.rm(), source.offset() + 1)); 12361cb0ef41Sopenharmony_ci Lbu(rd, source); 12371cb0ef41Sopenharmony_ci#endif 12381cb0ef41Sopenharmony_ci } 12391cb0ef41Sopenharmony_ci dsll(rd, rd, 8); 12401cb0ef41Sopenharmony_ci or_(rd, rd, scratch); 12411cb0ef41Sopenharmony_ci } 12421cb0ef41Sopenharmony_ci} 12431cb0ef41Sopenharmony_ci 12441cb0ef41Sopenharmony_civoid TurboAssembler::Ush(Register rd, const MemOperand& rs, Register scratch) { 12451cb0ef41Sopenharmony_ci DCHECK(rd != at); 12461cb0ef41Sopenharmony_ci DCHECK(rs.rm() != at); 12471cb0ef41Sopenharmony_ci DCHECK(rs.rm() != scratch); 12481cb0ef41Sopenharmony_ci DCHECK(scratch != at); 12491cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 12501cb0ef41Sopenharmony_ci Sh(rd, rs); 12511cb0ef41Sopenharmony_ci } else { 12521cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 12531cb0ef41Sopenharmony_ci MemOperand source = rs; 12541cb0ef41Sopenharmony_ci // Adjust offset for two accesses and check if offset + 1 fits into int16_t. 12551cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source, OffsetAccessType::TWO_ACCESSES, 1); 12561cb0ef41Sopenharmony_ci 12571cb0ef41Sopenharmony_ci if (scratch != rd) { 12581cb0ef41Sopenharmony_ci mov(scratch, rd); 12591cb0ef41Sopenharmony_ci } 12601cb0ef41Sopenharmony_ci 12611cb0ef41Sopenharmony_ci#if defined(V8_TARGET_LITTLE_ENDIAN) 12621cb0ef41Sopenharmony_ci Sb(scratch, source); 12631cb0ef41Sopenharmony_ci srl(scratch, scratch, 8); 12641cb0ef41Sopenharmony_ci Sb(scratch, MemOperand(source.rm(), source.offset() + 1)); 12651cb0ef41Sopenharmony_ci#elif defined(V8_TARGET_BIG_ENDIAN) 12661cb0ef41Sopenharmony_ci Sb(scratch, MemOperand(source.rm(), source.offset() + 1)); 12671cb0ef41Sopenharmony_ci srl(scratch, scratch, 8); 12681cb0ef41Sopenharmony_ci Sb(scratch, source); 12691cb0ef41Sopenharmony_ci#endif 12701cb0ef41Sopenharmony_ci } 12711cb0ef41Sopenharmony_ci} 12721cb0ef41Sopenharmony_ci 12731cb0ef41Sopenharmony_civoid TurboAssembler::Uld(Register rd, const MemOperand& rs) { 12741cb0ef41Sopenharmony_ci DCHECK(rd != at); 12751cb0ef41Sopenharmony_ci DCHECK(rs.rm() != at); 12761cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 12771cb0ef41Sopenharmony_ci Ld(rd, rs); 12781cb0ef41Sopenharmony_ci } else { 12791cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 12801cb0ef41Sopenharmony_ci DCHECK(kMipsLdrOffset <= 7 && kMipsLdlOffset <= 7); 12811cb0ef41Sopenharmony_ci MemOperand source = rs; 12821cb0ef41Sopenharmony_ci // Adjust offset for two accesses and check if offset + 7 fits into int16_t. 12831cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source, OffsetAccessType::TWO_ACCESSES, 7); 12841cb0ef41Sopenharmony_ci if (rd != source.rm()) { 12851cb0ef41Sopenharmony_ci ldr(rd, MemOperand(source.rm(), source.offset() + kMipsLdrOffset)); 12861cb0ef41Sopenharmony_ci ldl(rd, MemOperand(source.rm(), source.offset() + kMipsLdlOffset)); 12871cb0ef41Sopenharmony_ci } else { 12881cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 12891cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 12901cb0ef41Sopenharmony_ci ldr(scratch, MemOperand(rs.rm(), rs.offset() + kMipsLdrOffset)); 12911cb0ef41Sopenharmony_ci ldl(scratch, MemOperand(rs.rm(), rs.offset() + kMipsLdlOffset)); 12921cb0ef41Sopenharmony_ci mov(rd, scratch); 12931cb0ef41Sopenharmony_ci } 12941cb0ef41Sopenharmony_ci } 12951cb0ef41Sopenharmony_ci} 12961cb0ef41Sopenharmony_ci 12971cb0ef41Sopenharmony_ci// Load consequent 32-bit word pair in 64-bit reg. and put first word in low 12981cb0ef41Sopenharmony_ci// bits, 12991cb0ef41Sopenharmony_ci// second word in high bits. 13001cb0ef41Sopenharmony_civoid MacroAssembler::LoadWordPair(Register rd, const MemOperand& rs, 13011cb0ef41Sopenharmony_ci Register scratch) { 13021cb0ef41Sopenharmony_ci Lwu(rd, rs); 13031cb0ef41Sopenharmony_ci Lw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); 13041cb0ef41Sopenharmony_ci dsll32(scratch, scratch, 0); 13051cb0ef41Sopenharmony_ci Daddu(rd, rd, scratch); 13061cb0ef41Sopenharmony_ci} 13071cb0ef41Sopenharmony_ci 13081cb0ef41Sopenharmony_civoid TurboAssembler::Usd(Register rd, const MemOperand& rs) { 13091cb0ef41Sopenharmony_ci DCHECK(rd != at); 13101cb0ef41Sopenharmony_ci DCHECK(rs.rm() != at); 13111cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 13121cb0ef41Sopenharmony_ci Sd(rd, rs); 13131cb0ef41Sopenharmony_ci } else { 13141cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 13151cb0ef41Sopenharmony_ci DCHECK(kMipsSdrOffset <= 7 && kMipsSdlOffset <= 7); 13161cb0ef41Sopenharmony_ci MemOperand source = rs; 13171cb0ef41Sopenharmony_ci // Adjust offset for two accesses and check if offset + 7 fits into int16_t. 13181cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source, OffsetAccessType::TWO_ACCESSES, 7); 13191cb0ef41Sopenharmony_ci sdr(rd, MemOperand(source.rm(), source.offset() + kMipsSdrOffset)); 13201cb0ef41Sopenharmony_ci sdl(rd, MemOperand(source.rm(), source.offset() + kMipsSdlOffset)); 13211cb0ef41Sopenharmony_ci } 13221cb0ef41Sopenharmony_ci} 13231cb0ef41Sopenharmony_ci 13241cb0ef41Sopenharmony_ci// Do 64-bit store as two consequent 32-bit stores to unaligned address. 13251cb0ef41Sopenharmony_civoid MacroAssembler::StoreWordPair(Register rd, const MemOperand& rs, 13261cb0ef41Sopenharmony_ci Register scratch) { 13271cb0ef41Sopenharmony_ci Sw(rd, rs); 13281cb0ef41Sopenharmony_ci dsrl32(scratch, rd, 0); 13291cb0ef41Sopenharmony_ci Sw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); 13301cb0ef41Sopenharmony_ci} 13311cb0ef41Sopenharmony_ci 13321cb0ef41Sopenharmony_civoid TurboAssembler::Ulwc1(FPURegister fd, const MemOperand& rs, 13331cb0ef41Sopenharmony_ci Register scratch) { 13341cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 13351cb0ef41Sopenharmony_ci Lwc1(fd, rs); 13361cb0ef41Sopenharmony_ci } else { 13371cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 13381cb0ef41Sopenharmony_ci Ulw(scratch, rs); 13391cb0ef41Sopenharmony_ci mtc1(scratch, fd); 13401cb0ef41Sopenharmony_ci } 13411cb0ef41Sopenharmony_ci} 13421cb0ef41Sopenharmony_ci 13431cb0ef41Sopenharmony_civoid TurboAssembler::Uswc1(FPURegister fd, const MemOperand& rs, 13441cb0ef41Sopenharmony_ci Register scratch) { 13451cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 13461cb0ef41Sopenharmony_ci Swc1(fd, rs); 13471cb0ef41Sopenharmony_ci } else { 13481cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 13491cb0ef41Sopenharmony_ci mfc1(scratch, fd); 13501cb0ef41Sopenharmony_ci Usw(scratch, rs); 13511cb0ef41Sopenharmony_ci } 13521cb0ef41Sopenharmony_ci} 13531cb0ef41Sopenharmony_ci 13541cb0ef41Sopenharmony_civoid TurboAssembler::Uldc1(FPURegister fd, const MemOperand& rs, 13551cb0ef41Sopenharmony_ci Register scratch) { 13561cb0ef41Sopenharmony_ci DCHECK(scratch != at); 13571cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 13581cb0ef41Sopenharmony_ci Ldc1(fd, rs); 13591cb0ef41Sopenharmony_ci } else { 13601cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 13611cb0ef41Sopenharmony_ci Uld(scratch, rs); 13621cb0ef41Sopenharmony_ci dmtc1(scratch, fd); 13631cb0ef41Sopenharmony_ci } 13641cb0ef41Sopenharmony_ci} 13651cb0ef41Sopenharmony_ci 13661cb0ef41Sopenharmony_civoid TurboAssembler::Usdc1(FPURegister fd, const MemOperand& rs, 13671cb0ef41Sopenharmony_ci Register scratch) { 13681cb0ef41Sopenharmony_ci DCHECK(scratch != at); 13691cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 13701cb0ef41Sopenharmony_ci Sdc1(fd, rs); 13711cb0ef41Sopenharmony_ci } else { 13721cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 13731cb0ef41Sopenharmony_ci dmfc1(scratch, fd); 13741cb0ef41Sopenharmony_ci Usd(scratch, rs); 13751cb0ef41Sopenharmony_ci } 13761cb0ef41Sopenharmony_ci} 13771cb0ef41Sopenharmony_ci 13781cb0ef41Sopenharmony_civoid TurboAssembler::Lb(Register rd, const MemOperand& rs) { 13791cb0ef41Sopenharmony_ci MemOperand source = rs; 13801cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); 13811cb0ef41Sopenharmony_ci lb(rd, source); 13821cb0ef41Sopenharmony_ci} 13831cb0ef41Sopenharmony_ci 13841cb0ef41Sopenharmony_civoid TurboAssembler::Lbu(Register rd, const MemOperand& rs) { 13851cb0ef41Sopenharmony_ci MemOperand source = rs; 13861cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); 13871cb0ef41Sopenharmony_ci lbu(rd, source); 13881cb0ef41Sopenharmony_ci} 13891cb0ef41Sopenharmony_ci 13901cb0ef41Sopenharmony_civoid TurboAssembler::Sb(Register rd, const MemOperand& rs) { 13911cb0ef41Sopenharmony_ci MemOperand source = rs; 13921cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); 13931cb0ef41Sopenharmony_ci sb(rd, source); 13941cb0ef41Sopenharmony_ci} 13951cb0ef41Sopenharmony_ci 13961cb0ef41Sopenharmony_civoid TurboAssembler::Lh(Register rd, const MemOperand& rs) { 13971cb0ef41Sopenharmony_ci MemOperand source = rs; 13981cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); 13991cb0ef41Sopenharmony_ci lh(rd, source); 14001cb0ef41Sopenharmony_ci} 14011cb0ef41Sopenharmony_ci 14021cb0ef41Sopenharmony_civoid TurboAssembler::Lhu(Register rd, const MemOperand& rs) { 14031cb0ef41Sopenharmony_ci MemOperand source = rs; 14041cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); 14051cb0ef41Sopenharmony_ci lhu(rd, source); 14061cb0ef41Sopenharmony_ci} 14071cb0ef41Sopenharmony_ci 14081cb0ef41Sopenharmony_civoid TurboAssembler::Sh(Register rd, const MemOperand& rs) { 14091cb0ef41Sopenharmony_ci MemOperand source = rs; 14101cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); 14111cb0ef41Sopenharmony_ci sh(rd, source); 14121cb0ef41Sopenharmony_ci} 14131cb0ef41Sopenharmony_ci 14141cb0ef41Sopenharmony_civoid TurboAssembler::Lw(Register rd, const MemOperand& rs) { 14151cb0ef41Sopenharmony_ci MemOperand source = rs; 14161cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); 14171cb0ef41Sopenharmony_ci lw(rd, source); 14181cb0ef41Sopenharmony_ci} 14191cb0ef41Sopenharmony_ci 14201cb0ef41Sopenharmony_civoid TurboAssembler::Lwu(Register rd, const MemOperand& rs) { 14211cb0ef41Sopenharmony_ci MemOperand source = rs; 14221cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); 14231cb0ef41Sopenharmony_ci lwu(rd, source); 14241cb0ef41Sopenharmony_ci} 14251cb0ef41Sopenharmony_ci 14261cb0ef41Sopenharmony_civoid TurboAssembler::Sw(Register rd, const MemOperand& rs) { 14271cb0ef41Sopenharmony_ci MemOperand source = rs; 14281cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); 14291cb0ef41Sopenharmony_ci sw(rd, source); 14301cb0ef41Sopenharmony_ci} 14311cb0ef41Sopenharmony_ci 14321cb0ef41Sopenharmony_civoid TurboAssembler::Ld(Register rd, const MemOperand& rs) { 14331cb0ef41Sopenharmony_ci MemOperand source = rs; 14341cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); 14351cb0ef41Sopenharmony_ci ld(rd, source); 14361cb0ef41Sopenharmony_ci} 14371cb0ef41Sopenharmony_ci 14381cb0ef41Sopenharmony_civoid TurboAssembler::Sd(Register rd, const MemOperand& rs) { 14391cb0ef41Sopenharmony_ci MemOperand source = rs; 14401cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&source); 14411cb0ef41Sopenharmony_ci sd(rd, source); 14421cb0ef41Sopenharmony_ci} 14431cb0ef41Sopenharmony_ci 14441cb0ef41Sopenharmony_civoid TurboAssembler::Lwc1(FPURegister fd, const MemOperand& src) { 14451cb0ef41Sopenharmony_ci MemOperand tmp = src; 14461cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&tmp); 14471cb0ef41Sopenharmony_ci lwc1(fd, tmp); 14481cb0ef41Sopenharmony_ci} 14491cb0ef41Sopenharmony_ci 14501cb0ef41Sopenharmony_civoid TurboAssembler::Swc1(FPURegister fs, const MemOperand& src) { 14511cb0ef41Sopenharmony_ci MemOperand tmp = src; 14521cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&tmp); 14531cb0ef41Sopenharmony_ci swc1(fs, tmp); 14541cb0ef41Sopenharmony_ci} 14551cb0ef41Sopenharmony_ci 14561cb0ef41Sopenharmony_civoid TurboAssembler::Ldc1(FPURegister fd, const MemOperand& src) { 14571cb0ef41Sopenharmony_ci MemOperand tmp = src; 14581cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&tmp); 14591cb0ef41Sopenharmony_ci ldc1(fd, tmp); 14601cb0ef41Sopenharmony_ci} 14611cb0ef41Sopenharmony_ci 14621cb0ef41Sopenharmony_civoid TurboAssembler::Sdc1(FPURegister fs, const MemOperand& src) { 14631cb0ef41Sopenharmony_ci MemOperand tmp = src; 14641cb0ef41Sopenharmony_ci AdjustBaseAndOffset(&tmp); 14651cb0ef41Sopenharmony_ci sdc1(fs, tmp); 14661cb0ef41Sopenharmony_ci} 14671cb0ef41Sopenharmony_ci 14681cb0ef41Sopenharmony_civoid TurboAssembler::Ll(Register rd, const MemOperand& rs) { 14691cb0ef41Sopenharmony_ci bool is_one_instruction = (kArchVariant == kMips64r6) ? is_int9(rs.offset()) 14701cb0ef41Sopenharmony_ci : is_int16(rs.offset()); 14711cb0ef41Sopenharmony_ci if (is_one_instruction) { 14721cb0ef41Sopenharmony_ci ll(rd, rs); 14731cb0ef41Sopenharmony_ci } else { 14741cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 14751cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 14761cb0ef41Sopenharmony_ci li(scratch, rs.offset()); 14771cb0ef41Sopenharmony_ci daddu(scratch, scratch, rs.rm()); 14781cb0ef41Sopenharmony_ci ll(rd, MemOperand(scratch, 0)); 14791cb0ef41Sopenharmony_ci } 14801cb0ef41Sopenharmony_ci} 14811cb0ef41Sopenharmony_ci 14821cb0ef41Sopenharmony_civoid TurboAssembler::Lld(Register rd, const MemOperand& rs) { 14831cb0ef41Sopenharmony_ci bool is_one_instruction = (kArchVariant == kMips64r6) ? is_int9(rs.offset()) 14841cb0ef41Sopenharmony_ci : is_int16(rs.offset()); 14851cb0ef41Sopenharmony_ci if (is_one_instruction) { 14861cb0ef41Sopenharmony_ci lld(rd, rs); 14871cb0ef41Sopenharmony_ci } else { 14881cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 14891cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 14901cb0ef41Sopenharmony_ci li(scratch, rs.offset()); 14911cb0ef41Sopenharmony_ci daddu(scratch, scratch, rs.rm()); 14921cb0ef41Sopenharmony_ci lld(rd, MemOperand(scratch, 0)); 14931cb0ef41Sopenharmony_ci } 14941cb0ef41Sopenharmony_ci} 14951cb0ef41Sopenharmony_ci 14961cb0ef41Sopenharmony_civoid TurboAssembler::Sc(Register rd, const MemOperand& rs) { 14971cb0ef41Sopenharmony_ci bool is_one_instruction = (kArchVariant == kMips64r6) ? is_int9(rs.offset()) 14981cb0ef41Sopenharmony_ci : is_int16(rs.offset()); 14991cb0ef41Sopenharmony_ci if (is_one_instruction) { 15001cb0ef41Sopenharmony_ci sc(rd, rs); 15011cb0ef41Sopenharmony_ci } else { 15021cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 15031cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 15041cb0ef41Sopenharmony_ci li(scratch, rs.offset()); 15051cb0ef41Sopenharmony_ci daddu(scratch, scratch, rs.rm()); 15061cb0ef41Sopenharmony_ci sc(rd, MemOperand(scratch, 0)); 15071cb0ef41Sopenharmony_ci } 15081cb0ef41Sopenharmony_ci} 15091cb0ef41Sopenharmony_ci 15101cb0ef41Sopenharmony_civoid TurboAssembler::Scd(Register rd, const MemOperand& rs) { 15111cb0ef41Sopenharmony_ci bool is_one_instruction = (kArchVariant == kMips64r6) ? is_int9(rs.offset()) 15121cb0ef41Sopenharmony_ci : is_int16(rs.offset()); 15131cb0ef41Sopenharmony_ci if (is_one_instruction) { 15141cb0ef41Sopenharmony_ci scd(rd, rs); 15151cb0ef41Sopenharmony_ci } else { 15161cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 15171cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 15181cb0ef41Sopenharmony_ci li(scratch, rs.offset()); 15191cb0ef41Sopenharmony_ci daddu(scratch, scratch, rs.rm()); 15201cb0ef41Sopenharmony_ci scd(rd, MemOperand(scratch, 0)); 15211cb0ef41Sopenharmony_ci } 15221cb0ef41Sopenharmony_ci} 15231cb0ef41Sopenharmony_ci 15241cb0ef41Sopenharmony_civoid TurboAssembler::li(Register dst, Handle<HeapObject> value, LiFlags mode) { 15251cb0ef41Sopenharmony_ci // TODO(jgruber,v8:8887): Also consider a root-relative load when generating 15261cb0ef41Sopenharmony_ci // non-isolate-independent code. In many cases it might be cheaper than 15271cb0ef41Sopenharmony_ci // embedding the relocatable value. 15281cb0ef41Sopenharmony_ci if (root_array_available_ && options().isolate_independent_code) { 15291cb0ef41Sopenharmony_ci IndirectLoadConstant(dst, value); 15301cb0ef41Sopenharmony_ci return; 15311cb0ef41Sopenharmony_ci } 15321cb0ef41Sopenharmony_ci li(dst, Operand(value), mode); 15331cb0ef41Sopenharmony_ci} 15341cb0ef41Sopenharmony_ci 15351cb0ef41Sopenharmony_civoid TurboAssembler::li(Register dst, ExternalReference value, LiFlags mode) { 15361cb0ef41Sopenharmony_ci // TODO(jgruber,v8:8887): Also consider a root-relative load when generating 15371cb0ef41Sopenharmony_ci // non-isolate-independent code. In many cases it might be cheaper than 15381cb0ef41Sopenharmony_ci // embedding the relocatable value. 15391cb0ef41Sopenharmony_ci if (root_array_available_ && options().isolate_independent_code) { 15401cb0ef41Sopenharmony_ci IndirectLoadExternalReference(dst, value); 15411cb0ef41Sopenharmony_ci return; 15421cb0ef41Sopenharmony_ci } 15431cb0ef41Sopenharmony_ci li(dst, Operand(value), mode); 15441cb0ef41Sopenharmony_ci} 15451cb0ef41Sopenharmony_ci 15461cb0ef41Sopenharmony_civoid TurboAssembler::li(Register dst, const StringConstantBase* string, 15471cb0ef41Sopenharmony_ci LiFlags mode) { 15481cb0ef41Sopenharmony_ci li(dst, Operand::EmbeddedStringConstant(string), mode); 15491cb0ef41Sopenharmony_ci} 15501cb0ef41Sopenharmony_ci 15511cb0ef41Sopenharmony_cistatic inline int InstrCountForLiLower32Bit(int64_t value) { 15521cb0ef41Sopenharmony_ci if (!is_int16(static_cast<int32_t>(value)) && (value & kUpper16MaskOf64) && 15531cb0ef41Sopenharmony_ci (value & kImm16Mask)) { 15541cb0ef41Sopenharmony_ci return 2; 15551cb0ef41Sopenharmony_ci } else { 15561cb0ef41Sopenharmony_ci return 1; 15571cb0ef41Sopenharmony_ci } 15581cb0ef41Sopenharmony_ci} 15591cb0ef41Sopenharmony_ci 15601cb0ef41Sopenharmony_civoid TurboAssembler::LiLower32BitHelper(Register rd, Operand j) { 15611cb0ef41Sopenharmony_ci if (is_int16(static_cast<int32_t>(j.immediate()))) { 15621cb0ef41Sopenharmony_ci daddiu(rd, zero_reg, (j.immediate() & kImm16Mask)); 15631cb0ef41Sopenharmony_ci } else if (!(j.immediate() & kUpper16MaskOf64)) { 15641cb0ef41Sopenharmony_ci ori(rd, zero_reg, j.immediate() & kImm16Mask); 15651cb0ef41Sopenharmony_ci } else { 15661cb0ef41Sopenharmony_ci lui(rd, j.immediate() >> kLuiShift & kImm16Mask); 15671cb0ef41Sopenharmony_ci if (j.immediate() & kImm16Mask) { 15681cb0ef41Sopenharmony_ci ori(rd, rd, j.immediate() & kImm16Mask); 15691cb0ef41Sopenharmony_ci } 15701cb0ef41Sopenharmony_ci } 15711cb0ef41Sopenharmony_ci} 15721cb0ef41Sopenharmony_ci 15731cb0ef41Sopenharmony_cistatic inline int InstrCountForLoadReplicatedConst32(int64_t value) { 15741cb0ef41Sopenharmony_ci uint32_t x = static_cast<uint32_t>(value); 15751cb0ef41Sopenharmony_ci uint32_t y = static_cast<uint32_t>(value >> 32); 15761cb0ef41Sopenharmony_ci 15771cb0ef41Sopenharmony_ci if (x == y) { 15781cb0ef41Sopenharmony_ci return (is_uint16(x) || is_int16(x) || (x & kImm16Mask) == 0) ? 2 : 3; 15791cb0ef41Sopenharmony_ci } 15801cb0ef41Sopenharmony_ci 15811cb0ef41Sopenharmony_ci return INT_MAX; 15821cb0ef41Sopenharmony_ci} 15831cb0ef41Sopenharmony_ci 15841cb0ef41Sopenharmony_ciint TurboAssembler::InstrCountForLi64Bit(int64_t value) { 15851cb0ef41Sopenharmony_ci if (is_int32(value)) { 15861cb0ef41Sopenharmony_ci return InstrCountForLiLower32Bit(value); 15871cb0ef41Sopenharmony_ci } else { 15881cb0ef41Sopenharmony_ci int bit31 = value >> 31 & 0x1; 15891cb0ef41Sopenharmony_ci if ((value & kUpper16MaskOf64) == 0 && is_int16(value >> 32) && 15901cb0ef41Sopenharmony_ci kArchVariant == kMips64r6) { 15911cb0ef41Sopenharmony_ci return 2; 15921cb0ef41Sopenharmony_ci } else if ((value & (kHigher16MaskOf64 | kUpper16MaskOf64)) == 0 && 15931cb0ef41Sopenharmony_ci kArchVariant == kMips64r6) { 15941cb0ef41Sopenharmony_ci return 2; 15951cb0ef41Sopenharmony_ci } else if ((value & kImm16Mask) == 0 && is_int16((value >> 32) + bit31) && 15961cb0ef41Sopenharmony_ci kArchVariant == kMips64r6) { 15971cb0ef41Sopenharmony_ci return 2; 15981cb0ef41Sopenharmony_ci } else if ((value & kImm16Mask) == 0 && 15991cb0ef41Sopenharmony_ci ((value >> 31) & 0x1FFFF) == ((0x20000 - bit31) & 0x1FFFF) && 16001cb0ef41Sopenharmony_ci kArchVariant == kMips64r6) { 16011cb0ef41Sopenharmony_ci return 2; 16021cb0ef41Sopenharmony_ci } else if (is_int16(static_cast<int32_t>(value)) && 16031cb0ef41Sopenharmony_ci is_int16((value >> 32) + bit31) && kArchVariant == kMips64r6) { 16041cb0ef41Sopenharmony_ci return 2; 16051cb0ef41Sopenharmony_ci } else if (is_int16(static_cast<int32_t>(value)) && 16061cb0ef41Sopenharmony_ci ((value >> 31) & 0x1FFFF) == ((0x20000 - bit31) & 0x1FFFF) && 16071cb0ef41Sopenharmony_ci kArchVariant == kMips64r6) { 16081cb0ef41Sopenharmony_ci return 2; 16091cb0ef41Sopenharmony_ci } else if (base::bits::IsPowerOfTwo(value + 1) || 16101cb0ef41Sopenharmony_ci value == std::numeric_limits<int64_t>::max()) { 16111cb0ef41Sopenharmony_ci return 2; 16121cb0ef41Sopenharmony_ci } else { 16131cb0ef41Sopenharmony_ci int shift_cnt = base::bits::CountTrailingZeros64(value); 16141cb0ef41Sopenharmony_ci int rep32_count = InstrCountForLoadReplicatedConst32(value); 16151cb0ef41Sopenharmony_ci int64_t tmp = value >> shift_cnt; 16161cb0ef41Sopenharmony_ci if (is_uint16(tmp)) { 16171cb0ef41Sopenharmony_ci return 2; 16181cb0ef41Sopenharmony_ci } else if (is_int16(tmp)) { 16191cb0ef41Sopenharmony_ci return 2; 16201cb0ef41Sopenharmony_ci } else if (rep32_count < 3) { 16211cb0ef41Sopenharmony_ci return 2; 16221cb0ef41Sopenharmony_ci } else if (is_int32(tmp)) { 16231cb0ef41Sopenharmony_ci return 3; 16241cb0ef41Sopenharmony_ci } else { 16251cb0ef41Sopenharmony_ci shift_cnt = 16 + base::bits::CountTrailingZeros64(value >> 16); 16261cb0ef41Sopenharmony_ci tmp = value >> shift_cnt; 16271cb0ef41Sopenharmony_ci if (is_uint16(tmp)) { 16281cb0ef41Sopenharmony_ci return 3; 16291cb0ef41Sopenharmony_ci } else if (is_int16(tmp)) { 16301cb0ef41Sopenharmony_ci return 3; 16311cb0ef41Sopenharmony_ci } else if (rep32_count < 4) { 16321cb0ef41Sopenharmony_ci return 3; 16331cb0ef41Sopenharmony_ci } else if (kArchVariant == kMips64r6) { 16341cb0ef41Sopenharmony_ci int64_t imm = value; 16351cb0ef41Sopenharmony_ci int count = InstrCountForLiLower32Bit(imm); 16361cb0ef41Sopenharmony_ci imm = (imm >> 32) + bit31; 16371cb0ef41Sopenharmony_ci if (imm & kImm16Mask) { 16381cb0ef41Sopenharmony_ci count++; 16391cb0ef41Sopenharmony_ci } 16401cb0ef41Sopenharmony_ci imm = (imm >> 16) + (imm >> 15 & 0x1); 16411cb0ef41Sopenharmony_ci if (imm & kImm16Mask) { 16421cb0ef41Sopenharmony_ci count++; 16431cb0ef41Sopenharmony_ci } 16441cb0ef41Sopenharmony_ci return count; 16451cb0ef41Sopenharmony_ci } else { 16461cb0ef41Sopenharmony_ci if (is_int48(value)) { 16471cb0ef41Sopenharmony_ci int64_t k = value >> 16; 16481cb0ef41Sopenharmony_ci int count = InstrCountForLiLower32Bit(k) + 1; 16491cb0ef41Sopenharmony_ci if (value & kImm16Mask) { 16501cb0ef41Sopenharmony_ci count++; 16511cb0ef41Sopenharmony_ci } 16521cb0ef41Sopenharmony_ci return count; 16531cb0ef41Sopenharmony_ci } else { 16541cb0ef41Sopenharmony_ci int64_t k = value >> 32; 16551cb0ef41Sopenharmony_ci int count = InstrCountForLiLower32Bit(k); 16561cb0ef41Sopenharmony_ci if ((value >> 16) & kImm16Mask) { 16571cb0ef41Sopenharmony_ci count += 3; 16581cb0ef41Sopenharmony_ci if (value & kImm16Mask) { 16591cb0ef41Sopenharmony_ci count++; 16601cb0ef41Sopenharmony_ci } 16611cb0ef41Sopenharmony_ci } else { 16621cb0ef41Sopenharmony_ci count++; 16631cb0ef41Sopenharmony_ci if (value & kImm16Mask) { 16641cb0ef41Sopenharmony_ci count++; 16651cb0ef41Sopenharmony_ci } 16661cb0ef41Sopenharmony_ci } 16671cb0ef41Sopenharmony_ci return count; 16681cb0ef41Sopenharmony_ci } 16691cb0ef41Sopenharmony_ci } 16701cb0ef41Sopenharmony_ci } 16711cb0ef41Sopenharmony_ci } 16721cb0ef41Sopenharmony_ci } 16731cb0ef41Sopenharmony_ci UNREACHABLE(); 16741cb0ef41Sopenharmony_ci return INT_MAX; 16751cb0ef41Sopenharmony_ci} 16761cb0ef41Sopenharmony_ci 16771cb0ef41Sopenharmony_ci// All changes to if...else conditions here must be added to 16781cb0ef41Sopenharmony_ci// InstrCountForLi64Bit as well. 16791cb0ef41Sopenharmony_civoid TurboAssembler::li_optimized(Register rd, Operand j, LiFlags mode) { 16801cb0ef41Sopenharmony_ci DCHECK(!j.is_reg()); 16811cb0ef41Sopenharmony_ci DCHECK(!MustUseReg(j.rmode())); 16821cb0ef41Sopenharmony_ci DCHECK(mode == OPTIMIZE_SIZE); 16831cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 16841cb0ef41Sopenharmony_ci // Normal load of an immediate value which does not need Relocation Info. 16851cb0ef41Sopenharmony_ci if (is_int32(j.immediate())) { 16861cb0ef41Sopenharmony_ci LiLower32BitHelper(rd, j); 16871cb0ef41Sopenharmony_ci } else { 16881cb0ef41Sopenharmony_ci int bit31 = j.immediate() >> 31 & 0x1; 16891cb0ef41Sopenharmony_ci if ((j.immediate() & kUpper16MaskOf64) == 0 && 16901cb0ef41Sopenharmony_ci is_int16(j.immediate() >> 32) && kArchVariant == kMips64r6) { 16911cb0ef41Sopenharmony_ci // 64-bit value which consists of an unsigned 16-bit value in its 16921cb0ef41Sopenharmony_ci // least significant 32-bits, and a signed 16-bit value in its 16931cb0ef41Sopenharmony_ci // most significant 32-bits. 16941cb0ef41Sopenharmony_ci ori(rd, zero_reg, j.immediate() & kImm16Mask); 16951cb0ef41Sopenharmony_ci dahi(rd, j.immediate() >> 32 & kImm16Mask); 16961cb0ef41Sopenharmony_ci } else if ((j.immediate() & (kHigher16MaskOf64 | kUpper16MaskOf64)) == 0 && 16971cb0ef41Sopenharmony_ci kArchVariant == kMips64r6) { 16981cb0ef41Sopenharmony_ci // 64-bit value which consists of an unsigned 16-bit value in its 16991cb0ef41Sopenharmony_ci // least significant 48-bits, and a signed 16-bit value in its 17001cb0ef41Sopenharmony_ci // most significant 16-bits. 17011cb0ef41Sopenharmony_ci ori(rd, zero_reg, j.immediate() & kImm16Mask); 17021cb0ef41Sopenharmony_ci dati(rd, j.immediate() >> 48 & kImm16Mask); 17031cb0ef41Sopenharmony_ci } else if ((j.immediate() & kImm16Mask) == 0 && 17041cb0ef41Sopenharmony_ci is_int16((j.immediate() >> 32) + bit31) && 17051cb0ef41Sopenharmony_ci kArchVariant == kMips64r6) { 17061cb0ef41Sopenharmony_ci // 16 LSBs (Least Significant Bits) all set to zero. 17071cb0ef41Sopenharmony_ci // 48 MSBs (Most Significant Bits) hold a signed 32-bit value. 17081cb0ef41Sopenharmony_ci lui(rd, j.immediate() >> kLuiShift & kImm16Mask); 17091cb0ef41Sopenharmony_ci dahi(rd, ((j.immediate() >> 32) + bit31) & kImm16Mask); 17101cb0ef41Sopenharmony_ci } else if ((j.immediate() & kImm16Mask) == 0 && 17111cb0ef41Sopenharmony_ci ((j.immediate() >> 31) & 0x1FFFF) == 17121cb0ef41Sopenharmony_ci ((0x20000 - bit31) & 0x1FFFF) && 17131cb0ef41Sopenharmony_ci kArchVariant == kMips64r6) { 17141cb0ef41Sopenharmony_ci // 16 LSBs all set to zero. 17151cb0ef41Sopenharmony_ci // 48 MSBs hold a signed value which can't be represented by signed 17161cb0ef41Sopenharmony_ci // 32-bit number, and the middle 16 bits are all zero, or all one. 17171cb0ef41Sopenharmony_ci lui(rd, j.immediate() >> kLuiShift & kImm16Mask); 17181cb0ef41Sopenharmony_ci dati(rd, ((j.immediate() >> 48) + bit31) & kImm16Mask); 17191cb0ef41Sopenharmony_ci } else if (is_int16(static_cast<int32_t>(j.immediate())) && 17201cb0ef41Sopenharmony_ci is_int16((j.immediate() >> 32) + bit31) && 17211cb0ef41Sopenharmony_ci kArchVariant == kMips64r6) { 17221cb0ef41Sopenharmony_ci // 32 LSBs contain a signed 16-bit number. 17231cb0ef41Sopenharmony_ci // 32 MSBs contain a signed 16-bit number. 17241cb0ef41Sopenharmony_ci daddiu(rd, zero_reg, j.immediate() & kImm16Mask); 17251cb0ef41Sopenharmony_ci dahi(rd, ((j.immediate() >> 32) + bit31) & kImm16Mask); 17261cb0ef41Sopenharmony_ci } else if (is_int16(static_cast<int32_t>(j.immediate())) && 17271cb0ef41Sopenharmony_ci ((j.immediate() >> 31) & 0x1FFFF) == 17281cb0ef41Sopenharmony_ci ((0x20000 - bit31) & 0x1FFFF) && 17291cb0ef41Sopenharmony_ci kArchVariant == kMips64r6) { 17301cb0ef41Sopenharmony_ci // 48 LSBs contain an unsigned 16-bit number. 17311cb0ef41Sopenharmony_ci // 16 MSBs contain a signed 16-bit number. 17321cb0ef41Sopenharmony_ci daddiu(rd, zero_reg, j.immediate() & kImm16Mask); 17331cb0ef41Sopenharmony_ci dati(rd, ((j.immediate() >> 48) + bit31) & kImm16Mask); 17341cb0ef41Sopenharmony_ci } else if (base::bits::IsPowerOfTwo(j.immediate() + 1) || 17351cb0ef41Sopenharmony_ci j.immediate() == std::numeric_limits<int64_t>::max()) { 17361cb0ef41Sopenharmony_ci // 64-bit values which have their "n" LSBs set to one, and their 17371cb0ef41Sopenharmony_ci // "64-n" MSBs set to zero. "n" must meet the restrictions 0 < n < 64. 17381cb0ef41Sopenharmony_ci int shift_cnt = 64 - base::bits::CountTrailingZeros64(j.immediate() + 1); 17391cb0ef41Sopenharmony_ci daddiu(rd, zero_reg, -1); 17401cb0ef41Sopenharmony_ci if (shift_cnt < 32) { 17411cb0ef41Sopenharmony_ci dsrl(rd, rd, shift_cnt); 17421cb0ef41Sopenharmony_ci } else { 17431cb0ef41Sopenharmony_ci dsrl32(rd, rd, shift_cnt & 31); 17441cb0ef41Sopenharmony_ci } 17451cb0ef41Sopenharmony_ci } else { 17461cb0ef41Sopenharmony_ci int shift_cnt = base::bits::CountTrailingZeros64(j.immediate()); 17471cb0ef41Sopenharmony_ci int rep32_count = InstrCountForLoadReplicatedConst32(j.immediate()); 17481cb0ef41Sopenharmony_ci int64_t tmp = j.immediate() >> shift_cnt; 17491cb0ef41Sopenharmony_ci if (is_uint16(tmp)) { 17501cb0ef41Sopenharmony_ci // Value can be computed by loading a 16-bit unsigned value, and 17511cb0ef41Sopenharmony_ci // then shifting left. 17521cb0ef41Sopenharmony_ci ori(rd, zero_reg, tmp & kImm16Mask); 17531cb0ef41Sopenharmony_ci if (shift_cnt < 32) { 17541cb0ef41Sopenharmony_ci dsll(rd, rd, shift_cnt); 17551cb0ef41Sopenharmony_ci } else { 17561cb0ef41Sopenharmony_ci dsll32(rd, rd, shift_cnt & 31); 17571cb0ef41Sopenharmony_ci } 17581cb0ef41Sopenharmony_ci } else if (is_int16(tmp)) { 17591cb0ef41Sopenharmony_ci // Value can be computed by loading a 16-bit signed value, and 17601cb0ef41Sopenharmony_ci // then shifting left. 17611cb0ef41Sopenharmony_ci daddiu(rd, zero_reg, static_cast<int32_t>(tmp)); 17621cb0ef41Sopenharmony_ci if (shift_cnt < 32) { 17631cb0ef41Sopenharmony_ci dsll(rd, rd, shift_cnt); 17641cb0ef41Sopenharmony_ci } else { 17651cb0ef41Sopenharmony_ci dsll32(rd, rd, shift_cnt & 31); 17661cb0ef41Sopenharmony_ci } 17671cb0ef41Sopenharmony_ci } else if (rep32_count < 3) { 17681cb0ef41Sopenharmony_ci // Value being loaded has 32 LSBs equal to the 32 MSBs, and the 17691cb0ef41Sopenharmony_ci // value loaded into the 32 LSBs can be loaded with a single 17701cb0ef41Sopenharmony_ci // MIPS instruction. 17711cb0ef41Sopenharmony_ci LiLower32BitHelper(rd, j); 17721cb0ef41Sopenharmony_ci Dins(rd, rd, 32, 32); 17731cb0ef41Sopenharmony_ci } else if (is_int32(tmp)) { 17741cb0ef41Sopenharmony_ci // Loads with 3 instructions. 17751cb0ef41Sopenharmony_ci // Value can be computed by loading a 32-bit signed value, and 17761cb0ef41Sopenharmony_ci // then shifting left. 17771cb0ef41Sopenharmony_ci lui(rd, tmp >> kLuiShift & kImm16Mask); 17781cb0ef41Sopenharmony_ci ori(rd, rd, tmp & kImm16Mask); 17791cb0ef41Sopenharmony_ci if (shift_cnt < 32) { 17801cb0ef41Sopenharmony_ci dsll(rd, rd, shift_cnt); 17811cb0ef41Sopenharmony_ci } else { 17821cb0ef41Sopenharmony_ci dsll32(rd, rd, shift_cnt & 31); 17831cb0ef41Sopenharmony_ci } 17841cb0ef41Sopenharmony_ci } else { 17851cb0ef41Sopenharmony_ci shift_cnt = 16 + base::bits::CountTrailingZeros64(j.immediate() >> 16); 17861cb0ef41Sopenharmony_ci tmp = j.immediate() >> shift_cnt; 17871cb0ef41Sopenharmony_ci if (is_uint16(tmp)) { 17881cb0ef41Sopenharmony_ci // Value can be computed by loading a 16-bit unsigned value, 17891cb0ef41Sopenharmony_ci // shifting left, and "or"ing in another 16-bit unsigned value. 17901cb0ef41Sopenharmony_ci ori(rd, zero_reg, tmp & kImm16Mask); 17911cb0ef41Sopenharmony_ci if (shift_cnt < 32) { 17921cb0ef41Sopenharmony_ci dsll(rd, rd, shift_cnt); 17931cb0ef41Sopenharmony_ci } else { 17941cb0ef41Sopenharmony_ci dsll32(rd, rd, shift_cnt & 31); 17951cb0ef41Sopenharmony_ci } 17961cb0ef41Sopenharmony_ci ori(rd, rd, j.immediate() & kImm16Mask); 17971cb0ef41Sopenharmony_ci } else if (is_int16(tmp)) { 17981cb0ef41Sopenharmony_ci // Value can be computed by loading a 16-bit signed value, 17991cb0ef41Sopenharmony_ci // shifting left, and "or"ing in a 16-bit unsigned value. 18001cb0ef41Sopenharmony_ci daddiu(rd, zero_reg, static_cast<int32_t>(tmp)); 18011cb0ef41Sopenharmony_ci if (shift_cnt < 32) { 18021cb0ef41Sopenharmony_ci dsll(rd, rd, shift_cnt); 18031cb0ef41Sopenharmony_ci } else { 18041cb0ef41Sopenharmony_ci dsll32(rd, rd, shift_cnt & 31); 18051cb0ef41Sopenharmony_ci } 18061cb0ef41Sopenharmony_ci ori(rd, rd, j.immediate() & kImm16Mask); 18071cb0ef41Sopenharmony_ci } else if (rep32_count < 4) { 18081cb0ef41Sopenharmony_ci // Value being loaded has 32 LSBs equal to the 32 MSBs, and the 18091cb0ef41Sopenharmony_ci // value in the 32 LSBs requires 2 MIPS instructions to load. 18101cb0ef41Sopenharmony_ci LiLower32BitHelper(rd, j); 18111cb0ef41Sopenharmony_ci Dins(rd, rd, 32, 32); 18121cb0ef41Sopenharmony_ci } else if (kArchVariant == kMips64r6) { 18131cb0ef41Sopenharmony_ci // Loads with 3-4 instructions. 18141cb0ef41Sopenharmony_ci // Catch-all case to get any other 64-bit values which aren't 18151cb0ef41Sopenharmony_ci // handled by special cases above. 18161cb0ef41Sopenharmony_ci int64_t imm = j.immediate(); 18171cb0ef41Sopenharmony_ci LiLower32BitHelper(rd, j); 18181cb0ef41Sopenharmony_ci imm = (imm >> 32) + bit31; 18191cb0ef41Sopenharmony_ci if (imm & kImm16Mask) { 18201cb0ef41Sopenharmony_ci dahi(rd, imm & kImm16Mask); 18211cb0ef41Sopenharmony_ci } 18221cb0ef41Sopenharmony_ci imm = (imm >> 16) + (imm >> 15 & 0x1); 18231cb0ef41Sopenharmony_ci if (imm & kImm16Mask) { 18241cb0ef41Sopenharmony_ci dati(rd, imm & kImm16Mask); 18251cb0ef41Sopenharmony_ci } 18261cb0ef41Sopenharmony_ci } else { 18271cb0ef41Sopenharmony_ci if (is_int48(j.immediate())) { 18281cb0ef41Sopenharmony_ci Operand k = Operand(j.immediate() >> 16); 18291cb0ef41Sopenharmony_ci LiLower32BitHelper(rd, k); 18301cb0ef41Sopenharmony_ci dsll(rd, rd, 16); 18311cb0ef41Sopenharmony_ci if (j.immediate() & kImm16Mask) { 18321cb0ef41Sopenharmony_ci ori(rd, rd, j.immediate() & kImm16Mask); 18331cb0ef41Sopenharmony_ci } 18341cb0ef41Sopenharmony_ci } else { 18351cb0ef41Sopenharmony_ci Operand k = Operand(j.immediate() >> 32); 18361cb0ef41Sopenharmony_ci LiLower32BitHelper(rd, k); 18371cb0ef41Sopenharmony_ci if ((j.immediate() >> 16) & kImm16Mask) { 18381cb0ef41Sopenharmony_ci dsll(rd, rd, 16); 18391cb0ef41Sopenharmony_ci ori(rd, rd, (j.immediate() >> 16) & kImm16Mask); 18401cb0ef41Sopenharmony_ci dsll(rd, rd, 16); 18411cb0ef41Sopenharmony_ci if (j.immediate() & kImm16Mask) { 18421cb0ef41Sopenharmony_ci ori(rd, rd, j.immediate() & kImm16Mask); 18431cb0ef41Sopenharmony_ci } 18441cb0ef41Sopenharmony_ci } else { 18451cb0ef41Sopenharmony_ci dsll32(rd, rd, 0); 18461cb0ef41Sopenharmony_ci if (j.immediate() & kImm16Mask) { 18471cb0ef41Sopenharmony_ci ori(rd, rd, j.immediate() & kImm16Mask); 18481cb0ef41Sopenharmony_ci } 18491cb0ef41Sopenharmony_ci } 18501cb0ef41Sopenharmony_ci } 18511cb0ef41Sopenharmony_ci } 18521cb0ef41Sopenharmony_ci } 18531cb0ef41Sopenharmony_ci } 18541cb0ef41Sopenharmony_ci } 18551cb0ef41Sopenharmony_ci} 18561cb0ef41Sopenharmony_ci 18571cb0ef41Sopenharmony_civoid TurboAssembler::li(Register rd, Operand j, LiFlags mode) { 18581cb0ef41Sopenharmony_ci DCHECK(!j.is_reg()); 18591cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 18601cb0ef41Sopenharmony_ci if (!MustUseReg(j.rmode()) && mode == OPTIMIZE_SIZE) { 18611cb0ef41Sopenharmony_ci int li_count = InstrCountForLi64Bit(j.immediate()); 18621cb0ef41Sopenharmony_ci int li_neg_count = InstrCountForLi64Bit(-j.immediate()); 18631cb0ef41Sopenharmony_ci int li_not_count = InstrCountForLi64Bit(~j.immediate()); 18641cb0ef41Sopenharmony_ci // Loading -MIN_INT64 could cause problems, but loading MIN_INT64 takes only 18651cb0ef41Sopenharmony_ci // two instructions so no need to check for this. 18661cb0ef41Sopenharmony_ci if (li_neg_count <= li_not_count && li_neg_count < li_count - 1) { 18671cb0ef41Sopenharmony_ci DCHECK(j.immediate() != std::numeric_limits<int64_t>::min()); 18681cb0ef41Sopenharmony_ci li_optimized(rd, Operand(-j.immediate()), mode); 18691cb0ef41Sopenharmony_ci Dsubu(rd, zero_reg, rd); 18701cb0ef41Sopenharmony_ci } else if (li_neg_count > li_not_count && li_not_count < li_count - 1) { 18711cb0ef41Sopenharmony_ci DCHECK(j.immediate() != std::numeric_limits<int64_t>::min()); 18721cb0ef41Sopenharmony_ci li_optimized(rd, Operand(~j.immediate()), mode); 18731cb0ef41Sopenharmony_ci nor(rd, rd, rd); 18741cb0ef41Sopenharmony_ci } else { 18751cb0ef41Sopenharmony_ci li_optimized(rd, j, mode); 18761cb0ef41Sopenharmony_ci } 18771cb0ef41Sopenharmony_ci } else if (MustUseReg(j.rmode())) { 18781cb0ef41Sopenharmony_ci int64_t immediate; 18791cb0ef41Sopenharmony_ci if (j.IsHeapObjectRequest()) { 18801cb0ef41Sopenharmony_ci RequestHeapObject(j.heap_object_request()); 18811cb0ef41Sopenharmony_ci immediate = 0; 18821cb0ef41Sopenharmony_ci } else { 18831cb0ef41Sopenharmony_ci immediate = j.immediate(); 18841cb0ef41Sopenharmony_ci } 18851cb0ef41Sopenharmony_ci 18861cb0ef41Sopenharmony_ci RecordRelocInfo(j.rmode(), immediate); 18871cb0ef41Sopenharmony_ci lui(rd, (immediate >> 32) & kImm16Mask); 18881cb0ef41Sopenharmony_ci ori(rd, rd, (immediate >> 16) & kImm16Mask); 18891cb0ef41Sopenharmony_ci dsll(rd, rd, 16); 18901cb0ef41Sopenharmony_ci ori(rd, rd, immediate & kImm16Mask); 18911cb0ef41Sopenharmony_ci } else if (mode == ADDRESS_LOAD) { 18921cb0ef41Sopenharmony_ci // We always need the same number of instructions as we may need to patch 18931cb0ef41Sopenharmony_ci // this code to load another value which may need all 4 instructions. 18941cb0ef41Sopenharmony_ci lui(rd, (j.immediate() >> 32) & kImm16Mask); 18951cb0ef41Sopenharmony_ci ori(rd, rd, (j.immediate() >> 16) & kImm16Mask); 18961cb0ef41Sopenharmony_ci dsll(rd, rd, 16); 18971cb0ef41Sopenharmony_ci ori(rd, rd, j.immediate() & kImm16Mask); 18981cb0ef41Sopenharmony_ci } else { // mode == CONSTANT_SIZE - always emit the same instruction 18991cb0ef41Sopenharmony_ci // sequence. 19001cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 19011cb0ef41Sopenharmony_ci int64_t imm = j.immediate(); 19021cb0ef41Sopenharmony_ci lui(rd, imm >> kLuiShift & kImm16Mask); 19031cb0ef41Sopenharmony_ci ori(rd, rd, (imm & kImm16Mask)); 19041cb0ef41Sopenharmony_ci imm = (imm >> 32) + ((imm >> 31) & 0x1); 19051cb0ef41Sopenharmony_ci dahi(rd, imm & kImm16Mask & kImm16Mask); 19061cb0ef41Sopenharmony_ci imm = (imm >> 16) + ((imm >> 15) & 0x1); 19071cb0ef41Sopenharmony_ci dati(rd, imm & kImm16Mask & kImm16Mask); 19081cb0ef41Sopenharmony_ci } else { 19091cb0ef41Sopenharmony_ci lui(rd, (j.immediate() >> 48) & kImm16Mask); 19101cb0ef41Sopenharmony_ci ori(rd, rd, (j.immediate() >> 32) & kImm16Mask); 19111cb0ef41Sopenharmony_ci dsll(rd, rd, 16); 19121cb0ef41Sopenharmony_ci ori(rd, rd, (j.immediate() >> 16) & kImm16Mask); 19131cb0ef41Sopenharmony_ci dsll(rd, rd, 16); 19141cb0ef41Sopenharmony_ci ori(rd, rd, j.immediate() & kImm16Mask); 19151cb0ef41Sopenharmony_ci } 19161cb0ef41Sopenharmony_ci } 19171cb0ef41Sopenharmony_ci} 19181cb0ef41Sopenharmony_ci 19191cb0ef41Sopenharmony_civoid TurboAssembler::MultiPush(RegList regs) { 19201cb0ef41Sopenharmony_ci int16_t num_to_push = regs.Count(); 19211cb0ef41Sopenharmony_ci int16_t stack_offset = num_to_push * kPointerSize; 19221cb0ef41Sopenharmony_ci 19231cb0ef41Sopenharmony_ci Dsubu(sp, sp, Operand(stack_offset)); 19241cb0ef41Sopenharmony_ci for (int16_t i = kNumRegisters - 1; i >= 0; i--) { 19251cb0ef41Sopenharmony_ci if ((regs.bits() & (1 << i)) != 0) { 19261cb0ef41Sopenharmony_ci stack_offset -= kPointerSize; 19271cb0ef41Sopenharmony_ci Sd(ToRegister(i), MemOperand(sp, stack_offset)); 19281cb0ef41Sopenharmony_ci } 19291cb0ef41Sopenharmony_ci } 19301cb0ef41Sopenharmony_ci} 19311cb0ef41Sopenharmony_ci 19321cb0ef41Sopenharmony_civoid TurboAssembler::MultiPop(RegList regs) { 19331cb0ef41Sopenharmony_ci int16_t stack_offset = 0; 19341cb0ef41Sopenharmony_ci 19351cb0ef41Sopenharmony_ci for (int16_t i = 0; i < kNumRegisters; i++) { 19361cb0ef41Sopenharmony_ci if ((regs.bits() & (1 << i)) != 0) { 19371cb0ef41Sopenharmony_ci Ld(ToRegister(i), MemOperand(sp, stack_offset)); 19381cb0ef41Sopenharmony_ci stack_offset += kPointerSize; 19391cb0ef41Sopenharmony_ci } 19401cb0ef41Sopenharmony_ci } 19411cb0ef41Sopenharmony_ci daddiu(sp, sp, stack_offset); 19421cb0ef41Sopenharmony_ci} 19431cb0ef41Sopenharmony_ci 19441cb0ef41Sopenharmony_civoid TurboAssembler::MultiPushFPU(DoubleRegList regs) { 19451cb0ef41Sopenharmony_ci int16_t num_to_push = regs.Count(); 19461cb0ef41Sopenharmony_ci int16_t stack_offset = num_to_push * kDoubleSize; 19471cb0ef41Sopenharmony_ci 19481cb0ef41Sopenharmony_ci Dsubu(sp, sp, Operand(stack_offset)); 19491cb0ef41Sopenharmony_ci for (int16_t i = kNumRegisters - 1; i >= 0; i--) { 19501cb0ef41Sopenharmony_ci if ((regs.bits() & (1 << i)) != 0) { 19511cb0ef41Sopenharmony_ci stack_offset -= kDoubleSize; 19521cb0ef41Sopenharmony_ci Sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); 19531cb0ef41Sopenharmony_ci } 19541cb0ef41Sopenharmony_ci } 19551cb0ef41Sopenharmony_ci} 19561cb0ef41Sopenharmony_ci 19571cb0ef41Sopenharmony_civoid TurboAssembler::MultiPopFPU(DoubleRegList regs) { 19581cb0ef41Sopenharmony_ci int16_t stack_offset = 0; 19591cb0ef41Sopenharmony_ci 19601cb0ef41Sopenharmony_ci for (int16_t i = 0; i < kNumRegisters; i++) { 19611cb0ef41Sopenharmony_ci if ((regs.bits() & (1 << i)) != 0) { 19621cb0ef41Sopenharmony_ci Ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); 19631cb0ef41Sopenharmony_ci stack_offset += kDoubleSize; 19641cb0ef41Sopenharmony_ci } 19651cb0ef41Sopenharmony_ci } 19661cb0ef41Sopenharmony_ci daddiu(sp, sp, stack_offset); 19671cb0ef41Sopenharmony_ci} 19681cb0ef41Sopenharmony_ci 19691cb0ef41Sopenharmony_civoid TurboAssembler::MultiPushMSA(DoubleRegList regs) { 19701cb0ef41Sopenharmony_ci int16_t num_to_push = regs.Count(); 19711cb0ef41Sopenharmony_ci int16_t stack_offset = num_to_push * kSimd128Size; 19721cb0ef41Sopenharmony_ci 19731cb0ef41Sopenharmony_ci Dsubu(sp, sp, Operand(stack_offset)); 19741cb0ef41Sopenharmony_ci for (int16_t i = kNumRegisters - 1; i >= 0; i--) { 19751cb0ef41Sopenharmony_ci if ((regs.bits() & (1 << i)) != 0) { 19761cb0ef41Sopenharmony_ci stack_offset -= kSimd128Size; 19771cb0ef41Sopenharmony_ci st_d(MSARegister::from_code(i), MemOperand(sp, stack_offset)); 19781cb0ef41Sopenharmony_ci } 19791cb0ef41Sopenharmony_ci } 19801cb0ef41Sopenharmony_ci} 19811cb0ef41Sopenharmony_ci 19821cb0ef41Sopenharmony_civoid TurboAssembler::MultiPopMSA(DoubleRegList regs) { 19831cb0ef41Sopenharmony_ci int16_t stack_offset = 0; 19841cb0ef41Sopenharmony_ci 19851cb0ef41Sopenharmony_ci for (int16_t i = 0; i < kNumRegisters; i++) { 19861cb0ef41Sopenharmony_ci if ((regs.bits() & (1 << i)) != 0) { 19871cb0ef41Sopenharmony_ci ld_d(MSARegister::from_code(i), MemOperand(sp, stack_offset)); 19881cb0ef41Sopenharmony_ci stack_offset += kSimd128Size; 19891cb0ef41Sopenharmony_ci } 19901cb0ef41Sopenharmony_ci } 19911cb0ef41Sopenharmony_ci daddiu(sp, sp, stack_offset); 19921cb0ef41Sopenharmony_ci} 19931cb0ef41Sopenharmony_ci 19941cb0ef41Sopenharmony_civoid TurboAssembler::Ext(Register rt, Register rs, uint16_t pos, 19951cb0ef41Sopenharmony_ci uint16_t size) { 19961cb0ef41Sopenharmony_ci DCHECK_LT(pos, 32); 19971cb0ef41Sopenharmony_ci DCHECK_LT(pos + size, 33); 19981cb0ef41Sopenharmony_ci ext_(rt, rs, pos, size); 19991cb0ef41Sopenharmony_ci} 20001cb0ef41Sopenharmony_ci 20011cb0ef41Sopenharmony_civoid TurboAssembler::Dext(Register rt, Register rs, uint16_t pos, 20021cb0ef41Sopenharmony_ci uint16_t size) { 20031cb0ef41Sopenharmony_ci DCHECK(pos < 64 && 0 < size && size <= 64 && 0 < pos + size && 20041cb0ef41Sopenharmony_ci pos + size <= 64); 20051cb0ef41Sopenharmony_ci if (size > 32) { 20061cb0ef41Sopenharmony_ci dextm_(rt, rs, pos, size); 20071cb0ef41Sopenharmony_ci } else if (pos >= 32) { 20081cb0ef41Sopenharmony_ci dextu_(rt, rs, pos, size); 20091cb0ef41Sopenharmony_ci } else { 20101cb0ef41Sopenharmony_ci dext_(rt, rs, pos, size); 20111cb0ef41Sopenharmony_ci } 20121cb0ef41Sopenharmony_ci} 20131cb0ef41Sopenharmony_ci 20141cb0ef41Sopenharmony_civoid TurboAssembler::Ins(Register rt, Register rs, uint16_t pos, 20151cb0ef41Sopenharmony_ci uint16_t size) { 20161cb0ef41Sopenharmony_ci DCHECK_LT(pos, 32); 20171cb0ef41Sopenharmony_ci DCHECK_LE(pos + size, 32); 20181cb0ef41Sopenharmony_ci DCHECK_NE(size, 0); 20191cb0ef41Sopenharmony_ci ins_(rt, rs, pos, size); 20201cb0ef41Sopenharmony_ci} 20211cb0ef41Sopenharmony_ci 20221cb0ef41Sopenharmony_civoid TurboAssembler::Dins(Register rt, Register rs, uint16_t pos, 20231cb0ef41Sopenharmony_ci uint16_t size) { 20241cb0ef41Sopenharmony_ci DCHECK(pos < 64 && 0 < size && size <= 64 && 0 < pos + size && 20251cb0ef41Sopenharmony_ci pos + size <= 64); 20261cb0ef41Sopenharmony_ci if (pos + size <= 32) { 20271cb0ef41Sopenharmony_ci dins_(rt, rs, pos, size); 20281cb0ef41Sopenharmony_ci } else if (pos < 32) { 20291cb0ef41Sopenharmony_ci dinsm_(rt, rs, pos, size); 20301cb0ef41Sopenharmony_ci } else { 20311cb0ef41Sopenharmony_ci dinsu_(rt, rs, pos, size); 20321cb0ef41Sopenharmony_ci } 20331cb0ef41Sopenharmony_ci} 20341cb0ef41Sopenharmony_ci 20351cb0ef41Sopenharmony_civoid TurboAssembler::ExtractBits(Register dest, Register source, Register pos, 20361cb0ef41Sopenharmony_ci int size, bool sign_extend) { 20371cb0ef41Sopenharmony_ci dsrav(dest, source, pos); 20381cb0ef41Sopenharmony_ci Dext(dest, dest, 0, size); 20391cb0ef41Sopenharmony_ci if (sign_extend) { 20401cb0ef41Sopenharmony_ci switch (size) { 20411cb0ef41Sopenharmony_ci case 8: 20421cb0ef41Sopenharmony_ci seb(dest, dest); 20431cb0ef41Sopenharmony_ci break; 20441cb0ef41Sopenharmony_ci case 16: 20451cb0ef41Sopenharmony_ci seh(dest, dest); 20461cb0ef41Sopenharmony_ci break; 20471cb0ef41Sopenharmony_ci case 32: 20481cb0ef41Sopenharmony_ci // sign-extend word 20491cb0ef41Sopenharmony_ci sll(dest, dest, 0); 20501cb0ef41Sopenharmony_ci break; 20511cb0ef41Sopenharmony_ci default: 20521cb0ef41Sopenharmony_ci UNREACHABLE(); 20531cb0ef41Sopenharmony_ci } 20541cb0ef41Sopenharmony_ci } 20551cb0ef41Sopenharmony_ci} 20561cb0ef41Sopenharmony_ci 20571cb0ef41Sopenharmony_civoid TurboAssembler::InsertBits(Register dest, Register source, Register pos, 20581cb0ef41Sopenharmony_ci int size) { 20591cb0ef41Sopenharmony_ci Dror(dest, dest, pos); 20601cb0ef41Sopenharmony_ci Dins(dest, source, 0, size); 20611cb0ef41Sopenharmony_ci { 20621cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 20631cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 20641cb0ef41Sopenharmony_ci Dsubu(scratch, zero_reg, pos); 20651cb0ef41Sopenharmony_ci Dror(dest, dest, scratch); 20661cb0ef41Sopenharmony_ci } 20671cb0ef41Sopenharmony_ci} 20681cb0ef41Sopenharmony_ci 20691cb0ef41Sopenharmony_civoid TurboAssembler::Neg_s(FPURegister fd, FPURegister fs) { 20701cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 20711cb0ef41Sopenharmony_ci // r6 neg_s changes the sign for NaN-like operands as well. 20721cb0ef41Sopenharmony_ci neg_s(fd, fs); 20731cb0ef41Sopenharmony_ci } else { 20741cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 20751cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 20761cb0ef41Sopenharmony_ci Label is_nan, done; 20771cb0ef41Sopenharmony_ci Register scratch1 = t8; 20781cb0ef41Sopenharmony_ci Register scratch2 = t9; 20791cb0ef41Sopenharmony_ci CompareIsNanF32(fs, fs); 20801cb0ef41Sopenharmony_ci BranchTrueShortF(&is_nan); 20811cb0ef41Sopenharmony_ci Branch(USE_DELAY_SLOT, &done); 20821cb0ef41Sopenharmony_ci // For NaN input, neg_s will return the same NaN value, 20831cb0ef41Sopenharmony_ci // while the sign has to be changed separately. 20841cb0ef41Sopenharmony_ci neg_s(fd, fs); // In delay slot. 20851cb0ef41Sopenharmony_ci bind(&is_nan); 20861cb0ef41Sopenharmony_ci mfc1(scratch1, fs); 20871cb0ef41Sopenharmony_ci li(scratch2, kBinary32SignMask); 20881cb0ef41Sopenharmony_ci Xor(scratch1, scratch1, scratch2); 20891cb0ef41Sopenharmony_ci mtc1(scratch1, fd); 20901cb0ef41Sopenharmony_ci bind(&done); 20911cb0ef41Sopenharmony_ci } 20921cb0ef41Sopenharmony_ci} 20931cb0ef41Sopenharmony_ci 20941cb0ef41Sopenharmony_civoid TurboAssembler::Neg_d(FPURegister fd, FPURegister fs) { 20951cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 20961cb0ef41Sopenharmony_ci // r6 neg_d changes the sign for NaN-like operands as well. 20971cb0ef41Sopenharmony_ci neg_d(fd, fs); 20981cb0ef41Sopenharmony_ci } else { 20991cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r2); 21001cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 21011cb0ef41Sopenharmony_ci Label is_nan, done; 21021cb0ef41Sopenharmony_ci Register scratch1 = t8; 21031cb0ef41Sopenharmony_ci Register scratch2 = t9; 21041cb0ef41Sopenharmony_ci CompareIsNanF64(fs, fs); 21051cb0ef41Sopenharmony_ci BranchTrueShortF(&is_nan); 21061cb0ef41Sopenharmony_ci Branch(USE_DELAY_SLOT, &done); 21071cb0ef41Sopenharmony_ci // For NaN input, neg_d will return the same NaN value, 21081cb0ef41Sopenharmony_ci // while the sign has to be changed separately. 21091cb0ef41Sopenharmony_ci neg_d(fd, fs); // In delay slot. 21101cb0ef41Sopenharmony_ci bind(&is_nan); 21111cb0ef41Sopenharmony_ci dmfc1(scratch1, fs); 21121cb0ef41Sopenharmony_ci li(scratch2, base::Double::kSignMask); 21131cb0ef41Sopenharmony_ci Xor(scratch1, scratch1, scratch2); 21141cb0ef41Sopenharmony_ci dmtc1(scratch1, fd); 21151cb0ef41Sopenharmony_ci bind(&done); 21161cb0ef41Sopenharmony_ci } 21171cb0ef41Sopenharmony_ci} 21181cb0ef41Sopenharmony_ci 21191cb0ef41Sopenharmony_civoid TurboAssembler::Cvt_d_uw(FPURegister fd, FPURegister fs) { 21201cb0ef41Sopenharmony_ci // Move the data from fs to t8. 21211cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 21221cb0ef41Sopenharmony_ci mfc1(t8, fs); 21231cb0ef41Sopenharmony_ci Cvt_d_uw(fd, t8); 21241cb0ef41Sopenharmony_ci} 21251cb0ef41Sopenharmony_ci 21261cb0ef41Sopenharmony_civoid TurboAssembler::Cvt_d_uw(FPURegister fd, Register rs) { 21271cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 21281cb0ef41Sopenharmony_ci 21291cb0ef41Sopenharmony_ci // Convert rs to a FP value in fd. 21301cb0ef41Sopenharmony_ci DCHECK(rs != t9); 21311cb0ef41Sopenharmony_ci DCHECK(rs != at); 21321cb0ef41Sopenharmony_ci 21331cb0ef41Sopenharmony_ci // Zero extend int32 in rs. 21341cb0ef41Sopenharmony_ci Dext(t9, rs, 0, 32); 21351cb0ef41Sopenharmony_ci dmtc1(t9, fd); 21361cb0ef41Sopenharmony_ci cvt_d_l(fd, fd); 21371cb0ef41Sopenharmony_ci} 21381cb0ef41Sopenharmony_ci 21391cb0ef41Sopenharmony_civoid TurboAssembler::Cvt_d_ul(FPURegister fd, FPURegister fs) { 21401cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 21411cb0ef41Sopenharmony_ci // Move the data from fs to t8. 21421cb0ef41Sopenharmony_ci dmfc1(t8, fs); 21431cb0ef41Sopenharmony_ci Cvt_d_ul(fd, t8); 21441cb0ef41Sopenharmony_ci} 21451cb0ef41Sopenharmony_ci 21461cb0ef41Sopenharmony_civoid TurboAssembler::Cvt_d_ul(FPURegister fd, Register rs) { 21471cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 21481cb0ef41Sopenharmony_ci // Convert rs to a FP value in fd. 21491cb0ef41Sopenharmony_ci 21501cb0ef41Sopenharmony_ci DCHECK(rs != t9); 21511cb0ef41Sopenharmony_ci DCHECK(rs != at); 21521cb0ef41Sopenharmony_ci 21531cb0ef41Sopenharmony_ci Label msb_clear, conversion_done; 21541cb0ef41Sopenharmony_ci 21551cb0ef41Sopenharmony_ci Branch(&msb_clear, ge, rs, Operand(zero_reg)); 21561cb0ef41Sopenharmony_ci 21571cb0ef41Sopenharmony_ci // Rs >= 2^63 21581cb0ef41Sopenharmony_ci andi(t9, rs, 1); 21591cb0ef41Sopenharmony_ci dsrl(rs, rs, 1); 21601cb0ef41Sopenharmony_ci or_(t9, t9, rs); 21611cb0ef41Sopenharmony_ci dmtc1(t9, fd); 21621cb0ef41Sopenharmony_ci cvt_d_l(fd, fd); 21631cb0ef41Sopenharmony_ci Branch(USE_DELAY_SLOT, &conversion_done); 21641cb0ef41Sopenharmony_ci add_d(fd, fd, fd); // In delay slot. 21651cb0ef41Sopenharmony_ci 21661cb0ef41Sopenharmony_ci bind(&msb_clear); 21671cb0ef41Sopenharmony_ci // Rs < 2^63, we can do simple conversion. 21681cb0ef41Sopenharmony_ci dmtc1(rs, fd); 21691cb0ef41Sopenharmony_ci cvt_d_l(fd, fd); 21701cb0ef41Sopenharmony_ci 21711cb0ef41Sopenharmony_ci bind(&conversion_done); 21721cb0ef41Sopenharmony_ci} 21731cb0ef41Sopenharmony_ci 21741cb0ef41Sopenharmony_civoid TurboAssembler::Cvt_s_uw(FPURegister fd, FPURegister fs) { 21751cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 21761cb0ef41Sopenharmony_ci // Move the data from fs to t8. 21771cb0ef41Sopenharmony_ci mfc1(t8, fs); 21781cb0ef41Sopenharmony_ci Cvt_s_uw(fd, t8); 21791cb0ef41Sopenharmony_ci} 21801cb0ef41Sopenharmony_ci 21811cb0ef41Sopenharmony_civoid TurboAssembler::Cvt_s_uw(FPURegister fd, Register rs) { 21821cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 21831cb0ef41Sopenharmony_ci // Convert rs to a FP value in fd. 21841cb0ef41Sopenharmony_ci DCHECK(rs != t9); 21851cb0ef41Sopenharmony_ci DCHECK(rs != at); 21861cb0ef41Sopenharmony_ci 21871cb0ef41Sopenharmony_ci // Zero extend int32 in rs. 21881cb0ef41Sopenharmony_ci Dext(t9, rs, 0, 32); 21891cb0ef41Sopenharmony_ci dmtc1(t9, fd); 21901cb0ef41Sopenharmony_ci cvt_s_l(fd, fd); 21911cb0ef41Sopenharmony_ci} 21921cb0ef41Sopenharmony_ci 21931cb0ef41Sopenharmony_civoid TurboAssembler::Cvt_s_ul(FPURegister fd, FPURegister fs) { 21941cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 21951cb0ef41Sopenharmony_ci // Move the data from fs to t8. 21961cb0ef41Sopenharmony_ci dmfc1(t8, fs); 21971cb0ef41Sopenharmony_ci Cvt_s_ul(fd, t8); 21981cb0ef41Sopenharmony_ci} 21991cb0ef41Sopenharmony_ci 22001cb0ef41Sopenharmony_civoid TurboAssembler::Cvt_s_ul(FPURegister fd, Register rs) { 22011cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 22021cb0ef41Sopenharmony_ci // Convert rs to a FP value in fd. 22031cb0ef41Sopenharmony_ci 22041cb0ef41Sopenharmony_ci DCHECK(rs != t9); 22051cb0ef41Sopenharmony_ci DCHECK(rs != at); 22061cb0ef41Sopenharmony_ci 22071cb0ef41Sopenharmony_ci Label positive, conversion_done; 22081cb0ef41Sopenharmony_ci 22091cb0ef41Sopenharmony_ci Branch(&positive, ge, rs, Operand(zero_reg)); 22101cb0ef41Sopenharmony_ci 22111cb0ef41Sopenharmony_ci // Rs >= 2^31. 22121cb0ef41Sopenharmony_ci andi(t9, rs, 1); 22131cb0ef41Sopenharmony_ci dsrl(rs, rs, 1); 22141cb0ef41Sopenharmony_ci or_(t9, t9, rs); 22151cb0ef41Sopenharmony_ci dmtc1(t9, fd); 22161cb0ef41Sopenharmony_ci cvt_s_l(fd, fd); 22171cb0ef41Sopenharmony_ci Branch(USE_DELAY_SLOT, &conversion_done); 22181cb0ef41Sopenharmony_ci add_s(fd, fd, fd); // In delay slot. 22191cb0ef41Sopenharmony_ci 22201cb0ef41Sopenharmony_ci bind(&positive); 22211cb0ef41Sopenharmony_ci // Rs < 2^31, we can do simple conversion. 22221cb0ef41Sopenharmony_ci dmtc1(rs, fd); 22231cb0ef41Sopenharmony_ci cvt_s_l(fd, fd); 22241cb0ef41Sopenharmony_ci 22251cb0ef41Sopenharmony_ci bind(&conversion_done); 22261cb0ef41Sopenharmony_ci} 22271cb0ef41Sopenharmony_ci 22281cb0ef41Sopenharmony_civoid MacroAssembler::Round_l_d(FPURegister fd, FPURegister fs) { 22291cb0ef41Sopenharmony_ci round_l_d(fd, fs); 22301cb0ef41Sopenharmony_ci} 22311cb0ef41Sopenharmony_ci 22321cb0ef41Sopenharmony_civoid MacroAssembler::Floor_l_d(FPURegister fd, FPURegister fs) { 22331cb0ef41Sopenharmony_ci floor_l_d(fd, fs); 22341cb0ef41Sopenharmony_ci} 22351cb0ef41Sopenharmony_ci 22361cb0ef41Sopenharmony_civoid MacroAssembler::Ceil_l_d(FPURegister fd, FPURegister fs) { 22371cb0ef41Sopenharmony_ci ceil_l_d(fd, fs); 22381cb0ef41Sopenharmony_ci} 22391cb0ef41Sopenharmony_ci 22401cb0ef41Sopenharmony_civoid MacroAssembler::Trunc_l_d(FPURegister fd, FPURegister fs) { 22411cb0ef41Sopenharmony_ci trunc_l_d(fd, fs); 22421cb0ef41Sopenharmony_ci} 22431cb0ef41Sopenharmony_ci 22441cb0ef41Sopenharmony_civoid MacroAssembler::Trunc_l_ud(FPURegister fd, FPURegister fs, 22451cb0ef41Sopenharmony_ci FPURegister scratch) { 22461cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 22471cb0ef41Sopenharmony_ci // Load to GPR. 22481cb0ef41Sopenharmony_ci dmfc1(t8, fs); 22491cb0ef41Sopenharmony_ci // Reset sign bit. 22501cb0ef41Sopenharmony_ci { 22511cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 22521cb0ef41Sopenharmony_ci Register scratch1 = temps.Acquire(); 22531cb0ef41Sopenharmony_ci li(scratch1, 0x7FFFFFFFFFFFFFFF); 22541cb0ef41Sopenharmony_ci and_(t8, t8, scratch1); 22551cb0ef41Sopenharmony_ci } 22561cb0ef41Sopenharmony_ci dmtc1(t8, fs); 22571cb0ef41Sopenharmony_ci trunc_l_d(fd, fs); 22581cb0ef41Sopenharmony_ci} 22591cb0ef41Sopenharmony_ci 22601cb0ef41Sopenharmony_civoid TurboAssembler::Trunc_uw_d(FPURegister fd, FPURegister fs, 22611cb0ef41Sopenharmony_ci FPURegister scratch) { 22621cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 22631cb0ef41Sopenharmony_ci Trunc_uw_d(t8, fs, scratch); 22641cb0ef41Sopenharmony_ci mtc1(t8, fd); 22651cb0ef41Sopenharmony_ci} 22661cb0ef41Sopenharmony_ci 22671cb0ef41Sopenharmony_civoid TurboAssembler::Trunc_uw_s(FPURegister fd, FPURegister fs, 22681cb0ef41Sopenharmony_ci FPURegister scratch) { 22691cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 22701cb0ef41Sopenharmony_ci Trunc_uw_s(t8, fs, scratch); 22711cb0ef41Sopenharmony_ci mtc1(t8, fd); 22721cb0ef41Sopenharmony_ci} 22731cb0ef41Sopenharmony_ci 22741cb0ef41Sopenharmony_civoid TurboAssembler::Trunc_ul_d(FPURegister fd, FPURegister fs, 22751cb0ef41Sopenharmony_ci FPURegister scratch, Register result) { 22761cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 22771cb0ef41Sopenharmony_ci Trunc_ul_d(t8, fs, scratch, result); 22781cb0ef41Sopenharmony_ci dmtc1(t8, fd); 22791cb0ef41Sopenharmony_ci} 22801cb0ef41Sopenharmony_ci 22811cb0ef41Sopenharmony_civoid TurboAssembler::Trunc_ul_s(FPURegister fd, FPURegister fs, 22821cb0ef41Sopenharmony_ci FPURegister scratch, Register result) { 22831cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 22841cb0ef41Sopenharmony_ci Trunc_ul_s(t8, fs, scratch, result); 22851cb0ef41Sopenharmony_ci dmtc1(t8, fd); 22861cb0ef41Sopenharmony_ci} 22871cb0ef41Sopenharmony_ci 22881cb0ef41Sopenharmony_civoid MacroAssembler::Trunc_w_d(FPURegister fd, FPURegister fs) { 22891cb0ef41Sopenharmony_ci trunc_w_d(fd, fs); 22901cb0ef41Sopenharmony_ci} 22911cb0ef41Sopenharmony_ci 22921cb0ef41Sopenharmony_civoid MacroAssembler::Round_w_d(FPURegister fd, FPURegister fs) { 22931cb0ef41Sopenharmony_ci round_w_d(fd, fs); 22941cb0ef41Sopenharmony_ci} 22951cb0ef41Sopenharmony_ci 22961cb0ef41Sopenharmony_civoid MacroAssembler::Floor_w_d(FPURegister fd, FPURegister fs) { 22971cb0ef41Sopenharmony_ci floor_w_d(fd, fs); 22981cb0ef41Sopenharmony_ci} 22991cb0ef41Sopenharmony_ci 23001cb0ef41Sopenharmony_civoid MacroAssembler::Ceil_w_d(FPURegister fd, FPURegister fs) { 23011cb0ef41Sopenharmony_ci ceil_w_d(fd, fs); 23021cb0ef41Sopenharmony_ci} 23031cb0ef41Sopenharmony_ci 23041cb0ef41Sopenharmony_civoid TurboAssembler::Trunc_uw_d(Register rd, FPURegister fs, 23051cb0ef41Sopenharmony_ci FPURegister scratch) { 23061cb0ef41Sopenharmony_ci DCHECK(fs != scratch); 23071cb0ef41Sopenharmony_ci DCHECK(rd != at); 23081cb0ef41Sopenharmony_ci 23091cb0ef41Sopenharmony_ci { 23101cb0ef41Sopenharmony_ci // Load 2^31 into scratch as its float representation. 23111cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 23121cb0ef41Sopenharmony_ci Register scratch1 = temps.Acquire(); 23131cb0ef41Sopenharmony_ci li(scratch1, 0x41E00000); 23141cb0ef41Sopenharmony_ci mtc1(zero_reg, scratch); 23151cb0ef41Sopenharmony_ci mthc1(scratch1, scratch); 23161cb0ef41Sopenharmony_ci } 23171cb0ef41Sopenharmony_ci // Test if scratch > fd. 23181cb0ef41Sopenharmony_ci // If fd < 2^31 we can convert it normally. 23191cb0ef41Sopenharmony_ci Label simple_convert; 23201cb0ef41Sopenharmony_ci CompareF64(OLT, fs, scratch); 23211cb0ef41Sopenharmony_ci BranchTrueShortF(&simple_convert); 23221cb0ef41Sopenharmony_ci 23231cb0ef41Sopenharmony_ci // First we subtract 2^31 from fd, then trunc it to rs 23241cb0ef41Sopenharmony_ci // and add 2^31 to rs. 23251cb0ef41Sopenharmony_ci sub_d(scratch, fs, scratch); 23261cb0ef41Sopenharmony_ci trunc_w_d(scratch, scratch); 23271cb0ef41Sopenharmony_ci mfc1(rd, scratch); 23281cb0ef41Sopenharmony_ci Or(rd, rd, 1 << 31); 23291cb0ef41Sopenharmony_ci 23301cb0ef41Sopenharmony_ci Label done; 23311cb0ef41Sopenharmony_ci Branch(&done); 23321cb0ef41Sopenharmony_ci // Simple conversion. 23331cb0ef41Sopenharmony_ci bind(&simple_convert); 23341cb0ef41Sopenharmony_ci trunc_w_d(scratch, fs); 23351cb0ef41Sopenharmony_ci mfc1(rd, scratch); 23361cb0ef41Sopenharmony_ci 23371cb0ef41Sopenharmony_ci bind(&done); 23381cb0ef41Sopenharmony_ci} 23391cb0ef41Sopenharmony_ci 23401cb0ef41Sopenharmony_civoid TurboAssembler::Trunc_uw_s(Register rd, FPURegister fs, 23411cb0ef41Sopenharmony_ci FPURegister scratch) { 23421cb0ef41Sopenharmony_ci DCHECK(fs != scratch); 23431cb0ef41Sopenharmony_ci DCHECK(rd != at); 23441cb0ef41Sopenharmony_ci 23451cb0ef41Sopenharmony_ci { 23461cb0ef41Sopenharmony_ci // Load 2^31 into scratch as its float representation. 23471cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 23481cb0ef41Sopenharmony_ci Register scratch1 = temps.Acquire(); 23491cb0ef41Sopenharmony_ci li(scratch1, 0x4F000000); 23501cb0ef41Sopenharmony_ci mtc1(scratch1, scratch); 23511cb0ef41Sopenharmony_ci } 23521cb0ef41Sopenharmony_ci // Test if scratch > fs. 23531cb0ef41Sopenharmony_ci // If fs < 2^31 we can convert it normally. 23541cb0ef41Sopenharmony_ci Label simple_convert; 23551cb0ef41Sopenharmony_ci CompareF32(OLT, fs, scratch); 23561cb0ef41Sopenharmony_ci BranchTrueShortF(&simple_convert); 23571cb0ef41Sopenharmony_ci 23581cb0ef41Sopenharmony_ci // First we subtract 2^31 from fs, then trunc it to rd 23591cb0ef41Sopenharmony_ci // and add 2^31 to rd. 23601cb0ef41Sopenharmony_ci sub_s(scratch, fs, scratch); 23611cb0ef41Sopenharmony_ci trunc_w_s(scratch, scratch); 23621cb0ef41Sopenharmony_ci mfc1(rd, scratch); 23631cb0ef41Sopenharmony_ci Or(rd, rd, 1 << 31); 23641cb0ef41Sopenharmony_ci 23651cb0ef41Sopenharmony_ci Label done; 23661cb0ef41Sopenharmony_ci Branch(&done); 23671cb0ef41Sopenharmony_ci // Simple conversion. 23681cb0ef41Sopenharmony_ci bind(&simple_convert); 23691cb0ef41Sopenharmony_ci trunc_w_s(scratch, fs); 23701cb0ef41Sopenharmony_ci mfc1(rd, scratch); 23711cb0ef41Sopenharmony_ci 23721cb0ef41Sopenharmony_ci bind(&done); 23731cb0ef41Sopenharmony_ci} 23741cb0ef41Sopenharmony_ci 23751cb0ef41Sopenharmony_civoid TurboAssembler::Trunc_ul_d(Register rd, FPURegister fs, 23761cb0ef41Sopenharmony_ci FPURegister scratch, Register result) { 23771cb0ef41Sopenharmony_ci DCHECK(fs != scratch); 23781cb0ef41Sopenharmony_ci DCHECK(result.is_valid() ? !AreAliased(rd, result, at) : !AreAliased(rd, at)); 23791cb0ef41Sopenharmony_ci 23801cb0ef41Sopenharmony_ci Label simple_convert, done, fail; 23811cb0ef41Sopenharmony_ci if (result.is_valid()) { 23821cb0ef41Sopenharmony_ci mov(result, zero_reg); 23831cb0ef41Sopenharmony_ci Move(scratch, -1.0); 23841cb0ef41Sopenharmony_ci // If fd =< -1 or unordered, then the conversion fails. 23851cb0ef41Sopenharmony_ci CompareF64(OLE, fs, scratch); 23861cb0ef41Sopenharmony_ci BranchTrueShortF(&fail); 23871cb0ef41Sopenharmony_ci CompareIsNanF64(fs, scratch); 23881cb0ef41Sopenharmony_ci BranchTrueShortF(&fail); 23891cb0ef41Sopenharmony_ci } 23901cb0ef41Sopenharmony_ci 23911cb0ef41Sopenharmony_ci // Load 2^63 into scratch as its double representation. 23921cb0ef41Sopenharmony_ci li(at, 0x43E0000000000000); 23931cb0ef41Sopenharmony_ci dmtc1(at, scratch); 23941cb0ef41Sopenharmony_ci 23951cb0ef41Sopenharmony_ci // Test if scratch > fs. 23961cb0ef41Sopenharmony_ci // If fs < 2^63 we can convert it normally. 23971cb0ef41Sopenharmony_ci CompareF64(OLT, fs, scratch); 23981cb0ef41Sopenharmony_ci BranchTrueShortF(&simple_convert); 23991cb0ef41Sopenharmony_ci 24001cb0ef41Sopenharmony_ci // First we subtract 2^63 from fs, then trunc it to rd 24011cb0ef41Sopenharmony_ci // and add 2^63 to rd. 24021cb0ef41Sopenharmony_ci sub_d(scratch, fs, scratch); 24031cb0ef41Sopenharmony_ci trunc_l_d(scratch, scratch); 24041cb0ef41Sopenharmony_ci dmfc1(rd, scratch); 24051cb0ef41Sopenharmony_ci Or(rd, rd, Operand(1UL << 63)); 24061cb0ef41Sopenharmony_ci Branch(&done); 24071cb0ef41Sopenharmony_ci 24081cb0ef41Sopenharmony_ci // Simple conversion. 24091cb0ef41Sopenharmony_ci bind(&simple_convert); 24101cb0ef41Sopenharmony_ci trunc_l_d(scratch, fs); 24111cb0ef41Sopenharmony_ci dmfc1(rd, scratch); 24121cb0ef41Sopenharmony_ci 24131cb0ef41Sopenharmony_ci bind(&done); 24141cb0ef41Sopenharmony_ci if (result.is_valid()) { 24151cb0ef41Sopenharmony_ci // Conversion is failed if the result is negative. 24161cb0ef41Sopenharmony_ci { 24171cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 24181cb0ef41Sopenharmony_ci Register scratch1 = temps.Acquire(); 24191cb0ef41Sopenharmony_ci addiu(scratch1, zero_reg, -1); 24201cb0ef41Sopenharmony_ci dsrl(scratch1, scratch1, 1); // Load 2^62. 24211cb0ef41Sopenharmony_ci dmfc1(result, scratch); 24221cb0ef41Sopenharmony_ci xor_(result, result, scratch1); 24231cb0ef41Sopenharmony_ci } 24241cb0ef41Sopenharmony_ci Slt(result, zero_reg, result); 24251cb0ef41Sopenharmony_ci } 24261cb0ef41Sopenharmony_ci 24271cb0ef41Sopenharmony_ci bind(&fail); 24281cb0ef41Sopenharmony_ci} 24291cb0ef41Sopenharmony_ci 24301cb0ef41Sopenharmony_civoid TurboAssembler::Trunc_ul_s(Register rd, FPURegister fs, 24311cb0ef41Sopenharmony_ci FPURegister scratch, Register result) { 24321cb0ef41Sopenharmony_ci DCHECK(fs != scratch); 24331cb0ef41Sopenharmony_ci DCHECK(result.is_valid() ? !AreAliased(rd, result, at) : !AreAliased(rd, at)); 24341cb0ef41Sopenharmony_ci 24351cb0ef41Sopenharmony_ci Label simple_convert, done, fail; 24361cb0ef41Sopenharmony_ci if (result.is_valid()) { 24371cb0ef41Sopenharmony_ci mov(result, zero_reg); 24381cb0ef41Sopenharmony_ci Move(scratch, -1.0f); 24391cb0ef41Sopenharmony_ci // If fd =< -1 or unordered, then the conversion fails. 24401cb0ef41Sopenharmony_ci CompareF32(OLE, fs, scratch); 24411cb0ef41Sopenharmony_ci BranchTrueShortF(&fail); 24421cb0ef41Sopenharmony_ci CompareIsNanF32(fs, scratch); 24431cb0ef41Sopenharmony_ci BranchTrueShortF(&fail); 24441cb0ef41Sopenharmony_ci } 24451cb0ef41Sopenharmony_ci 24461cb0ef41Sopenharmony_ci { 24471cb0ef41Sopenharmony_ci // Load 2^63 into scratch as its float representation. 24481cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 24491cb0ef41Sopenharmony_ci Register scratch1 = temps.Acquire(); 24501cb0ef41Sopenharmony_ci li(scratch1, 0x5F000000); 24511cb0ef41Sopenharmony_ci mtc1(scratch1, scratch); 24521cb0ef41Sopenharmony_ci } 24531cb0ef41Sopenharmony_ci 24541cb0ef41Sopenharmony_ci // Test if scratch > fs. 24551cb0ef41Sopenharmony_ci // If fs < 2^63 we can convert it normally. 24561cb0ef41Sopenharmony_ci CompareF32(OLT, fs, scratch); 24571cb0ef41Sopenharmony_ci BranchTrueShortF(&simple_convert); 24581cb0ef41Sopenharmony_ci 24591cb0ef41Sopenharmony_ci // First we subtract 2^63 from fs, then trunc it to rd 24601cb0ef41Sopenharmony_ci // and add 2^63 to rd. 24611cb0ef41Sopenharmony_ci sub_s(scratch, fs, scratch); 24621cb0ef41Sopenharmony_ci trunc_l_s(scratch, scratch); 24631cb0ef41Sopenharmony_ci dmfc1(rd, scratch); 24641cb0ef41Sopenharmony_ci Or(rd, rd, Operand(1UL << 63)); 24651cb0ef41Sopenharmony_ci Branch(&done); 24661cb0ef41Sopenharmony_ci 24671cb0ef41Sopenharmony_ci // Simple conversion. 24681cb0ef41Sopenharmony_ci bind(&simple_convert); 24691cb0ef41Sopenharmony_ci trunc_l_s(scratch, fs); 24701cb0ef41Sopenharmony_ci dmfc1(rd, scratch); 24711cb0ef41Sopenharmony_ci 24721cb0ef41Sopenharmony_ci bind(&done); 24731cb0ef41Sopenharmony_ci if (result.is_valid()) { 24741cb0ef41Sopenharmony_ci // Conversion is failed if the result is negative or unordered. 24751cb0ef41Sopenharmony_ci { 24761cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 24771cb0ef41Sopenharmony_ci Register scratch1 = temps.Acquire(); 24781cb0ef41Sopenharmony_ci addiu(scratch1, zero_reg, -1); 24791cb0ef41Sopenharmony_ci dsrl(scratch1, scratch1, 1); // Load 2^62. 24801cb0ef41Sopenharmony_ci dmfc1(result, scratch); 24811cb0ef41Sopenharmony_ci xor_(result, result, scratch1); 24821cb0ef41Sopenharmony_ci } 24831cb0ef41Sopenharmony_ci Slt(result, zero_reg, result); 24841cb0ef41Sopenharmony_ci } 24851cb0ef41Sopenharmony_ci 24861cb0ef41Sopenharmony_ci bind(&fail); 24871cb0ef41Sopenharmony_ci} 24881cb0ef41Sopenharmony_ci 24891cb0ef41Sopenharmony_citemplate <typename RoundFunc> 24901cb0ef41Sopenharmony_civoid TurboAssembler::RoundDouble(FPURegister dst, FPURegister src, 24911cb0ef41Sopenharmony_ci FPURoundingMode mode, RoundFunc round) { 24921cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 24931cb0ef41Sopenharmony_ci Register scratch = t8; 24941cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 24951cb0ef41Sopenharmony_ci cfc1(scratch, FCSR); 24961cb0ef41Sopenharmony_ci li(at, Operand(mode)); 24971cb0ef41Sopenharmony_ci ctc1(at, FCSR); 24981cb0ef41Sopenharmony_ci rint_d(dst, src); 24991cb0ef41Sopenharmony_ci ctc1(scratch, FCSR); 25001cb0ef41Sopenharmony_ci } else { 25011cb0ef41Sopenharmony_ci Label done; 25021cb0ef41Sopenharmony_ci if (!IsDoubleZeroRegSet()) { 25031cb0ef41Sopenharmony_ci Move(kDoubleRegZero, 0.0); 25041cb0ef41Sopenharmony_ci } 25051cb0ef41Sopenharmony_ci mfhc1(scratch, src); 25061cb0ef41Sopenharmony_ci Ext(at, scratch, HeapNumber::kExponentShift, HeapNumber::kExponentBits); 25071cb0ef41Sopenharmony_ci Branch(USE_DELAY_SLOT, &done, hs, at, 25081cb0ef41Sopenharmony_ci Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits)); 25091cb0ef41Sopenharmony_ci // Canonicalize the result. 25101cb0ef41Sopenharmony_ci sub_d(dst, src, kDoubleRegZero); 25111cb0ef41Sopenharmony_ci round(this, dst, src); 25121cb0ef41Sopenharmony_ci dmfc1(at, dst); 25131cb0ef41Sopenharmony_ci Branch(USE_DELAY_SLOT, &done, ne, at, Operand(zero_reg)); 25141cb0ef41Sopenharmony_ci cvt_d_l(dst, dst); 25151cb0ef41Sopenharmony_ci srl(at, scratch, 31); 25161cb0ef41Sopenharmony_ci sll(at, at, 31); 25171cb0ef41Sopenharmony_ci mthc1(at, dst); 25181cb0ef41Sopenharmony_ci bind(&done); 25191cb0ef41Sopenharmony_ci } 25201cb0ef41Sopenharmony_ci} 25211cb0ef41Sopenharmony_ci 25221cb0ef41Sopenharmony_civoid TurboAssembler::Floor_d_d(FPURegister dst, FPURegister src) { 25231cb0ef41Sopenharmony_ci RoundDouble(dst, src, mode_floor, 25241cb0ef41Sopenharmony_ci [](TurboAssembler* tasm, FPURegister dst, FPURegister src) { 25251cb0ef41Sopenharmony_ci tasm->floor_l_d(dst, src); 25261cb0ef41Sopenharmony_ci }); 25271cb0ef41Sopenharmony_ci} 25281cb0ef41Sopenharmony_ci 25291cb0ef41Sopenharmony_civoid TurboAssembler::Ceil_d_d(FPURegister dst, FPURegister src) { 25301cb0ef41Sopenharmony_ci RoundDouble(dst, src, mode_ceil, 25311cb0ef41Sopenharmony_ci [](TurboAssembler* tasm, FPURegister dst, FPURegister src) { 25321cb0ef41Sopenharmony_ci tasm->ceil_l_d(dst, src); 25331cb0ef41Sopenharmony_ci }); 25341cb0ef41Sopenharmony_ci} 25351cb0ef41Sopenharmony_ci 25361cb0ef41Sopenharmony_civoid TurboAssembler::Trunc_d_d(FPURegister dst, FPURegister src) { 25371cb0ef41Sopenharmony_ci RoundDouble(dst, src, mode_trunc, 25381cb0ef41Sopenharmony_ci [](TurboAssembler* tasm, FPURegister dst, FPURegister src) { 25391cb0ef41Sopenharmony_ci tasm->trunc_l_d(dst, src); 25401cb0ef41Sopenharmony_ci }); 25411cb0ef41Sopenharmony_ci} 25421cb0ef41Sopenharmony_ci 25431cb0ef41Sopenharmony_civoid TurboAssembler::Round_d_d(FPURegister dst, FPURegister src) { 25441cb0ef41Sopenharmony_ci RoundDouble(dst, src, mode_round, 25451cb0ef41Sopenharmony_ci [](TurboAssembler* tasm, FPURegister dst, FPURegister src) { 25461cb0ef41Sopenharmony_ci tasm->round_l_d(dst, src); 25471cb0ef41Sopenharmony_ci }); 25481cb0ef41Sopenharmony_ci} 25491cb0ef41Sopenharmony_ci 25501cb0ef41Sopenharmony_citemplate <typename RoundFunc> 25511cb0ef41Sopenharmony_civoid TurboAssembler::RoundFloat(FPURegister dst, FPURegister src, 25521cb0ef41Sopenharmony_ci FPURoundingMode mode, RoundFunc round) { 25531cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 25541cb0ef41Sopenharmony_ci Register scratch = t8; 25551cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 25561cb0ef41Sopenharmony_ci cfc1(scratch, FCSR); 25571cb0ef41Sopenharmony_ci li(at, Operand(mode)); 25581cb0ef41Sopenharmony_ci ctc1(at, FCSR); 25591cb0ef41Sopenharmony_ci rint_s(dst, src); 25601cb0ef41Sopenharmony_ci ctc1(scratch, FCSR); 25611cb0ef41Sopenharmony_ci } else { 25621cb0ef41Sopenharmony_ci int32_t kFloat32ExponentBias = 127; 25631cb0ef41Sopenharmony_ci int32_t kFloat32MantissaBits = 23; 25641cb0ef41Sopenharmony_ci int32_t kFloat32ExponentBits = 8; 25651cb0ef41Sopenharmony_ci Label done; 25661cb0ef41Sopenharmony_ci if (!IsDoubleZeroRegSet()) { 25671cb0ef41Sopenharmony_ci Move(kDoubleRegZero, 0.0); 25681cb0ef41Sopenharmony_ci } 25691cb0ef41Sopenharmony_ci mfc1(scratch, src); 25701cb0ef41Sopenharmony_ci Ext(at, scratch, kFloat32MantissaBits, kFloat32ExponentBits); 25711cb0ef41Sopenharmony_ci Branch(USE_DELAY_SLOT, &done, hs, at, 25721cb0ef41Sopenharmony_ci Operand(kFloat32ExponentBias + kFloat32MantissaBits)); 25731cb0ef41Sopenharmony_ci // Canonicalize the result. 25741cb0ef41Sopenharmony_ci sub_s(dst, src, kDoubleRegZero); 25751cb0ef41Sopenharmony_ci round(this, dst, src); 25761cb0ef41Sopenharmony_ci mfc1(at, dst); 25771cb0ef41Sopenharmony_ci Branch(USE_DELAY_SLOT, &done, ne, at, Operand(zero_reg)); 25781cb0ef41Sopenharmony_ci cvt_s_w(dst, dst); 25791cb0ef41Sopenharmony_ci srl(at, scratch, 31); 25801cb0ef41Sopenharmony_ci sll(at, at, 31); 25811cb0ef41Sopenharmony_ci mtc1(at, dst); 25821cb0ef41Sopenharmony_ci bind(&done); 25831cb0ef41Sopenharmony_ci } 25841cb0ef41Sopenharmony_ci} 25851cb0ef41Sopenharmony_ci 25861cb0ef41Sopenharmony_civoid TurboAssembler::Floor_s_s(FPURegister dst, FPURegister src) { 25871cb0ef41Sopenharmony_ci RoundFloat(dst, src, mode_floor, 25881cb0ef41Sopenharmony_ci [](TurboAssembler* tasm, FPURegister dst, FPURegister src) { 25891cb0ef41Sopenharmony_ci tasm->floor_w_s(dst, src); 25901cb0ef41Sopenharmony_ci }); 25911cb0ef41Sopenharmony_ci} 25921cb0ef41Sopenharmony_ci 25931cb0ef41Sopenharmony_civoid TurboAssembler::Ceil_s_s(FPURegister dst, FPURegister src) { 25941cb0ef41Sopenharmony_ci RoundFloat(dst, src, mode_ceil, 25951cb0ef41Sopenharmony_ci [](TurboAssembler* tasm, FPURegister dst, FPURegister src) { 25961cb0ef41Sopenharmony_ci tasm->ceil_w_s(dst, src); 25971cb0ef41Sopenharmony_ci }); 25981cb0ef41Sopenharmony_ci} 25991cb0ef41Sopenharmony_ci 26001cb0ef41Sopenharmony_civoid TurboAssembler::Trunc_s_s(FPURegister dst, FPURegister src) { 26011cb0ef41Sopenharmony_ci RoundFloat(dst, src, mode_trunc, 26021cb0ef41Sopenharmony_ci [](TurboAssembler* tasm, FPURegister dst, FPURegister src) { 26031cb0ef41Sopenharmony_ci tasm->trunc_w_s(dst, src); 26041cb0ef41Sopenharmony_ci }); 26051cb0ef41Sopenharmony_ci} 26061cb0ef41Sopenharmony_ci 26071cb0ef41Sopenharmony_civoid TurboAssembler::Round_s_s(FPURegister dst, FPURegister src) { 26081cb0ef41Sopenharmony_ci RoundFloat(dst, src, mode_round, 26091cb0ef41Sopenharmony_ci [](TurboAssembler* tasm, FPURegister dst, FPURegister src) { 26101cb0ef41Sopenharmony_ci tasm->round_w_s(dst, src); 26111cb0ef41Sopenharmony_ci }); 26121cb0ef41Sopenharmony_ci} 26131cb0ef41Sopenharmony_ci 26141cb0ef41Sopenharmony_civoid TurboAssembler::LoadLane(MSASize sz, MSARegister dst, uint8_t laneidx, 26151cb0ef41Sopenharmony_ci MemOperand src) { 26161cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 26171cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 26181cb0ef41Sopenharmony_ci switch (sz) { 26191cb0ef41Sopenharmony_ci case MSA_B: 26201cb0ef41Sopenharmony_ci Lbu(scratch, src); 26211cb0ef41Sopenharmony_ci insert_b(dst, laneidx, scratch); 26221cb0ef41Sopenharmony_ci break; 26231cb0ef41Sopenharmony_ci case MSA_H: 26241cb0ef41Sopenharmony_ci Lhu(scratch, src); 26251cb0ef41Sopenharmony_ci insert_h(dst, laneidx, scratch); 26261cb0ef41Sopenharmony_ci break; 26271cb0ef41Sopenharmony_ci case MSA_W: 26281cb0ef41Sopenharmony_ci Lwu(scratch, src); 26291cb0ef41Sopenharmony_ci insert_w(dst, laneidx, scratch); 26301cb0ef41Sopenharmony_ci break; 26311cb0ef41Sopenharmony_ci case MSA_D: 26321cb0ef41Sopenharmony_ci Ld(scratch, src); 26331cb0ef41Sopenharmony_ci insert_d(dst, laneidx, scratch); 26341cb0ef41Sopenharmony_ci break; 26351cb0ef41Sopenharmony_ci default: 26361cb0ef41Sopenharmony_ci UNREACHABLE(); 26371cb0ef41Sopenharmony_ci } 26381cb0ef41Sopenharmony_ci} 26391cb0ef41Sopenharmony_ci 26401cb0ef41Sopenharmony_civoid TurboAssembler::StoreLane(MSASize sz, MSARegister src, uint8_t laneidx, 26411cb0ef41Sopenharmony_ci MemOperand dst) { 26421cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 26431cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 26441cb0ef41Sopenharmony_ci switch (sz) { 26451cb0ef41Sopenharmony_ci case MSA_B: 26461cb0ef41Sopenharmony_ci copy_u_b(scratch, src, laneidx); 26471cb0ef41Sopenharmony_ci Sb(scratch, dst); 26481cb0ef41Sopenharmony_ci break; 26491cb0ef41Sopenharmony_ci case MSA_H: 26501cb0ef41Sopenharmony_ci copy_u_h(scratch, src, laneidx); 26511cb0ef41Sopenharmony_ci Sh(scratch, dst); 26521cb0ef41Sopenharmony_ci break; 26531cb0ef41Sopenharmony_ci case MSA_W: 26541cb0ef41Sopenharmony_ci if (laneidx == 0) { 26551cb0ef41Sopenharmony_ci FPURegister src_reg = FPURegister::from_code(src.code()); 26561cb0ef41Sopenharmony_ci Swc1(src_reg, dst); 26571cb0ef41Sopenharmony_ci } else { 26581cb0ef41Sopenharmony_ci copy_u_w(scratch, src, laneidx); 26591cb0ef41Sopenharmony_ci Sw(scratch, dst); 26601cb0ef41Sopenharmony_ci } 26611cb0ef41Sopenharmony_ci break; 26621cb0ef41Sopenharmony_ci case MSA_D: 26631cb0ef41Sopenharmony_ci if (laneidx == 0) { 26641cb0ef41Sopenharmony_ci FPURegister src_reg = FPURegister::from_code(src.code()); 26651cb0ef41Sopenharmony_ci Sdc1(src_reg, dst); 26661cb0ef41Sopenharmony_ci } else { 26671cb0ef41Sopenharmony_ci copy_s_d(scratch, src, laneidx); 26681cb0ef41Sopenharmony_ci Sd(scratch, dst); 26691cb0ef41Sopenharmony_ci } 26701cb0ef41Sopenharmony_ci break; 26711cb0ef41Sopenharmony_ci default: 26721cb0ef41Sopenharmony_ci UNREACHABLE(); 26731cb0ef41Sopenharmony_ci } 26741cb0ef41Sopenharmony_ci} 26751cb0ef41Sopenharmony_ci 26761cb0ef41Sopenharmony_ci#define EXT_MUL_BINOP(type, ilv_instr, dotp_instr) \ 26771cb0ef41Sopenharmony_ci case type: \ 26781cb0ef41Sopenharmony_ci xor_v(kSimd128RegZero, kSimd128RegZero, kSimd128RegZero); \ 26791cb0ef41Sopenharmony_ci ilv_instr(kSimd128ScratchReg, kSimd128RegZero, src1); \ 26801cb0ef41Sopenharmony_ci ilv_instr(kSimd128RegZero, kSimd128RegZero, src2); \ 26811cb0ef41Sopenharmony_ci dotp_instr(dst, kSimd128ScratchReg, kSimd128RegZero); \ 26821cb0ef41Sopenharmony_ci break; 26831cb0ef41Sopenharmony_ci 26841cb0ef41Sopenharmony_civoid TurboAssembler::ExtMulLow(MSADataType type, MSARegister dst, 26851cb0ef41Sopenharmony_ci MSARegister src1, MSARegister src2) { 26861cb0ef41Sopenharmony_ci switch (type) { 26871cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAS8, ilvr_b, dotp_s_h) 26881cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAS16, ilvr_h, dotp_s_w) 26891cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAS32, ilvr_w, dotp_s_d) 26901cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAU8, ilvr_b, dotp_u_h) 26911cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAU16, ilvr_h, dotp_u_w) 26921cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAU32, ilvr_w, dotp_u_d) 26931cb0ef41Sopenharmony_ci default: 26941cb0ef41Sopenharmony_ci UNREACHABLE(); 26951cb0ef41Sopenharmony_ci } 26961cb0ef41Sopenharmony_ci} 26971cb0ef41Sopenharmony_ci 26981cb0ef41Sopenharmony_civoid TurboAssembler::ExtMulHigh(MSADataType type, MSARegister dst, 26991cb0ef41Sopenharmony_ci MSARegister src1, MSARegister src2) { 27001cb0ef41Sopenharmony_ci switch (type) { 27011cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAS8, ilvl_b, dotp_s_h) 27021cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAS16, ilvl_h, dotp_s_w) 27031cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAS32, ilvl_w, dotp_s_d) 27041cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAU8, ilvl_b, dotp_u_h) 27051cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAU16, ilvl_h, dotp_u_w) 27061cb0ef41Sopenharmony_ci EXT_MUL_BINOP(MSAU32, ilvl_w, dotp_u_d) 27071cb0ef41Sopenharmony_ci default: 27081cb0ef41Sopenharmony_ci UNREACHABLE(); 27091cb0ef41Sopenharmony_ci } 27101cb0ef41Sopenharmony_ci} 27111cb0ef41Sopenharmony_ci#undef EXT_MUL_BINOP 27121cb0ef41Sopenharmony_ci 27131cb0ef41Sopenharmony_civoid TurboAssembler::LoadSplat(MSASize sz, MSARegister dst, MemOperand src) { 27141cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 27151cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 27161cb0ef41Sopenharmony_ci switch (sz) { 27171cb0ef41Sopenharmony_ci case MSA_B: 27181cb0ef41Sopenharmony_ci Lb(scratch, src); 27191cb0ef41Sopenharmony_ci fill_b(dst, scratch); 27201cb0ef41Sopenharmony_ci break; 27211cb0ef41Sopenharmony_ci case MSA_H: 27221cb0ef41Sopenharmony_ci Lh(scratch, src); 27231cb0ef41Sopenharmony_ci fill_h(dst, scratch); 27241cb0ef41Sopenharmony_ci break; 27251cb0ef41Sopenharmony_ci case MSA_W: 27261cb0ef41Sopenharmony_ci Lw(scratch, src); 27271cb0ef41Sopenharmony_ci fill_w(dst, scratch); 27281cb0ef41Sopenharmony_ci break; 27291cb0ef41Sopenharmony_ci case MSA_D: 27301cb0ef41Sopenharmony_ci Ld(scratch, src); 27311cb0ef41Sopenharmony_ci fill_d(dst, scratch); 27321cb0ef41Sopenharmony_ci break; 27331cb0ef41Sopenharmony_ci default: 27341cb0ef41Sopenharmony_ci UNREACHABLE(); 27351cb0ef41Sopenharmony_ci } 27361cb0ef41Sopenharmony_ci} 27371cb0ef41Sopenharmony_ci 27381cb0ef41Sopenharmony_civoid TurboAssembler::ExtAddPairwise(MSADataType type, MSARegister dst, 27391cb0ef41Sopenharmony_ci MSARegister src) { 27401cb0ef41Sopenharmony_ci switch (type) { 27411cb0ef41Sopenharmony_ci case MSAS8: 27421cb0ef41Sopenharmony_ci hadd_s_h(dst, src, src); 27431cb0ef41Sopenharmony_ci break; 27441cb0ef41Sopenharmony_ci case MSAU8: 27451cb0ef41Sopenharmony_ci hadd_u_h(dst, src, src); 27461cb0ef41Sopenharmony_ci break; 27471cb0ef41Sopenharmony_ci case MSAS16: 27481cb0ef41Sopenharmony_ci hadd_s_w(dst, src, src); 27491cb0ef41Sopenharmony_ci break; 27501cb0ef41Sopenharmony_ci case MSAU16: 27511cb0ef41Sopenharmony_ci hadd_u_w(dst, src, src); 27521cb0ef41Sopenharmony_ci break; 27531cb0ef41Sopenharmony_ci default: 27541cb0ef41Sopenharmony_ci UNREACHABLE(); 27551cb0ef41Sopenharmony_ci } 27561cb0ef41Sopenharmony_ci} 27571cb0ef41Sopenharmony_ci 27581cb0ef41Sopenharmony_civoid TurboAssembler::MSARoundW(MSARegister dst, MSARegister src, 27591cb0ef41Sopenharmony_ci FPURoundingMode mode) { 27601cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 27611cb0ef41Sopenharmony_ci Register scratch = t8; 27621cb0ef41Sopenharmony_ci Register scratch2 = at; 27631cb0ef41Sopenharmony_ci cfcmsa(scratch, MSACSR); 27641cb0ef41Sopenharmony_ci if (mode == kRoundToNearest) { 27651cb0ef41Sopenharmony_ci scratch2 = zero_reg; 27661cb0ef41Sopenharmony_ci } else { 27671cb0ef41Sopenharmony_ci li(scratch2, Operand(mode)); 27681cb0ef41Sopenharmony_ci } 27691cb0ef41Sopenharmony_ci ctcmsa(MSACSR, scratch2); 27701cb0ef41Sopenharmony_ci frint_w(dst, src); 27711cb0ef41Sopenharmony_ci ctcmsa(MSACSR, scratch); 27721cb0ef41Sopenharmony_ci} 27731cb0ef41Sopenharmony_ci 27741cb0ef41Sopenharmony_civoid TurboAssembler::MSARoundD(MSARegister dst, MSARegister src, 27751cb0ef41Sopenharmony_ci FPURoundingMode mode) { 27761cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 27771cb0ef41Sopenharmony_ci Register scratch = t8; 27781cb0ef41Sopenharmony_ci Register scratch2 = at; 27791cb0ef41Sopenharmony_ci cfcmsa(scratch, MSACSR); 27801cb0ef41Sopenharmony_ci if (mode == kRoundToNearest) { 27811cb0ef41Sopenharmony_ci scratch2 = zero_reg; 27821cb0ef41Sopenharmony_ci } else { 27831cb0ef41Sopenharmony_ci li(scratch2, Operand(mode)); 27841cb0ef41Sopenharmony_ci } 27851cb0ef41Sopenharmony_ci ctcmsa(MSACSR, scratch2); 27861cb0ef41Sopenharmony_ci frint_d(dst, src); 27871cb0ef41Sopenharmony_ci ctcmsa(MSACSR, scratch); 27881cb0ef41Sopenharmony_ci} 27891cb0ef41Sopenharmony_ci 27901cb0ef41Sopenharmony_civoid MacroAssembler::Madd_s(FPURegister fd, FPURegister fr, FPURegister fs, 27911cb0ef41Sopenharmony_ci FPURegister ft, FPURegister scratch) { 27921cb0ef41Sopenharmony_ci DCHECK(fr != scratch && fs != scratch && ft != scratch); 27931cb0ef41Sopenharmony_ci mul_s(scratch, fs, ft); 27941cb0ef41Sopenharmony_ci add_s(fd, fr, scratch); 27951cb0ef41Sopenharmony_ci} 27961cb0ef41Sopenharmony_ci 27971cb0ef41Sopenharmony_civoid MacroAssembler::Madd_d(FPURegister fd, FPURegister fr, FPURegister fs, 27981cb0ef41Sopenharmony_ci FPURegister ft, FPURegister scratch) { 27991cb0ef41Sopenharmony_ci DCHECK(fr != scratch && fs != scratch && ft != scratch); 28001cb0ef41Sopenharmony_ci mul_d(scratch, fs, ft); 28011cb0ef41Sopenharmony_ci add_d(fd, fr, scratch); 28021cb0ef41Sopenharmony_ci} 28031cb0ef41Sopenharmony_ci 28041cb0ef41Sopenharmony_civoid MacroAssembler::Msub_s(FPURegister fd, FPURegister fr, FPURegister fs, 28051cb0ef41Sopenharmony_ci FPURegister ft, FPURegister scratch) { 28061cb0ef41Sopenharmony_ci DCHECK(fr != scratch && fs != scratch && ft != scratch); 28071cb0ef41Sopenharmony_ci mul_s(scratch, fs, ft); 28081cb0ef41Sopenharmony_ci sub_s(fd, scratch, fr); 28091cb0ef41Sopenharmony_ci} 28101cb0ef41Sopenharmony_ci 28111cb0ef41Sopenharmony_civoid MacroAssembler::Msub_d(FPURegister fd, FPURegister fr, FPURegister fs, 28121cb0ef41Sopenharmony_ci FPURegister ft, FPURegister scratch) { 28131cb0ef41Sopenharmony_ci DCHECK(fr != scratch && fs != scratch && ft != scratch); 28141cb0ef41Sopenharmony_ci mul_d(scratch, fs, ft); 28151cb0ef41Sopenharmony_ci sub_d(fd, scratch, fr); 28161cb0ef41Sopenharmony_ci} 28171cb0ef41Sopenharmony_ci 28181cb0ef41Sopenharmony_civoid TurboAssembler::CompareF(SecondaryField sizeField, FPUCondition cc, 28191cb0ef41Sopenharmony_ci FPURegister cmp1, FPURegister cmp2) { 28201cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 28211cb0ef41Sopenharmony_ci sizeField = sizeField == D ? L : W; 28221cb0ef41Sopenharmony_ci DCHECK(cmp1 != kDoubleCompareReg && cmp2 != kDoubleCompareReg); 28231cb0ef41Sopenharmony_ci cmp(cc, sizeField, kDoubleCompareReg, cmp1, cmp2); 28241cb0ef41Sopenharmony_ci } else { 28251cb0ef41Sopenharmony_ci c(cc, sizeField, cmp1, cmp2); 28261cb0ef41Sopenharmony_ci } 28271cb0ef41Sopenharmony_ci} 28281cb0ef41Sopenharmony_ci 28291cb0ef41Sopenharmony_civoid TurboAssembler::CompareIsNanF(SecondaryField sizeField, FPURegister cmp1, 28301cb0ef41Sopenharmony_ci FPURegister cmp2) { 28311cb0ef41Sopenharmony_ci CompareF(sizeField, UN, cmp1, cmp2); 28321cb0ef41Sopenharmony_ci} 28331cb0ef41Sopenharmony_ci 28341cb0ef41Sopenharmony_civoid TurboAssembler::BranchTrueShortF(Label* target, BranchDelaySlot bd) { 28351cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 28361cb0ef41Sopenharmony_ci bc1nez(target, kDoubleCompareReg); 28371cb0ef41Sopenharmony_ci } else { 28381cb0ef41Sopenharmony_ci bc1t(target); 28391cb0ef41Sopenharmony_ci } 28401cb0ef41Sopenharmony_ci if (bd == PROTECT) { 28411cb0ef41Sopenharmony_ci nop(); 28421cb0ef41Sopenharmony_ci } 28431cb0ef41Sopenharmony_ci} 28441cb0ef41Sopenharmony_ci 28451cb0ef41Sopenharmony_civoid TurboAssembler::BranchFalseShortF(Label* target, BranchDelaySlot bd) { 28461cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 28471cb0ef41Sopenharmony_ci bc1eqz(target, kDoubleCompareReg); 28481cb0ef41Sopenharmony_ci } else { 28491cb0ef41Sopenharmony_ci bc1f(target); 28501cb0ef41Sopenharmony_ci } 28511cb0ef41Sopenharmony_ci if (bd == PROTECT) { 28521cb0ef41Sopenharmony_ci nop(); 28531cb0ef41Sopenharmony_ci } 28541cb0ef41Sopenharmony_ci} 28551cb0ef41Sopenharmony_ci 28561cb0ef41Sopenharmony_civoid TurboAssembler::BranchTrueF(Label* target, BranchDelaySlot bd) { 28571cb0ef41Sopenharmony_ci bool long_branch = 28581cb0ef41Sopenharmony_ci target->is_bound() ? !is_near(target) : is_trampoline_emitted(); 28591cb0ef41Sopenharmony_ci if (long_branch) { 28601cb0ef41Sopenharmony_ci Label skip; 28611cb0ef41Sopenharmony_ci BranchFalseShortF(&skip); 28621cb0ef41Sopenharmony_ci BranchLong(target, bd); 28631cb0ef41Sopenharmony_ci bind(&skip); 28641cb0ef41Sopenharmony_ci } else { 28651cb0ef41Sopenharmony_ci BranchTrueShortF(target, bd); 28661cb0ef41Sopenharmony_ci } 28671cb0ef41Sopenharmony_ci} 28681cb0ef41Sopenharmony_ci 28691cb0ef41Sopenharmony_civoid TurboAssembler::BranchFalseF(Label* target, BranchDelaySlot bd) { 28701cb0ef41Sopenharmony_ci bool long_branch = 28711cb0ef41Sopenharmony_ci target->is_bound() ? !is_near(target) : is_trampoline_emitted(); 28721cb0ef41Sopenharmony_ci if (long_branch) { 28731cb0ef41Sopenharmony_ci Label skip; 28741cb0ef41Sopenharmony_ci BranchTrueShortF(&skip); 28751cb0ef41Sopenharmony_ci BranchLong(target, bd); 28761cb0ef41Sopenharmony_ci bind(&skip); 28771cb0ef41Sopenharmony_ci } else { 28781cb0ef41Sopenharmony_ci BranchFalseShortF(target, bd); 28791cb0ef41Sopenharmony_ci } 28801cb0ef41Sopenharmony_ci} 28811cb0ef41Sopenharmony_ci 28821cb0ef41Sopenharmony_civoid TurboAssembler::BranchMSA(Label* target, MSABranchDF df, 28831cb0ef41Sopenharmony_ci MSABranchCondition cond, MSARegister wt, 28841cb0ef41Sopenharmony_ci BranchDelaySlot bd) { 28851cb0ef41Sopenharmony_ci { 28861cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 28871cb0ef41Sopenharmony_ci 28881cb0ef41Sopenharmony_ci if (target) { 28891cb0ef41Sopenharmony_ci bool long_branch = 28901cb0ef41Sopenharmony_ci target->is_bound() ? !is_near(target) : is_trampoline_emitted(); 28911cb0ef41Sopenharmony_ci if (long_branch) { 28921cb0ef41Sopenharmony_ci Label skip; 28931cb0ef41Sopenharmony_ci MSABranchCondition neg_cond = NegateMSABranchCondition(cond); 28941cb0ef41Sopenharmony_ci BranchShortMSA(df, &skip, neg_cond, wt, bd); 28951cb0ef41Sopenharmony_ci BranchLong(target, bd); 28961cb0ef41Sopenharmony_ci bind(&skip); 28971cb0ef41Sopenharmony_ci } else { 28981cb0ef41Sopenharmony_ci BranchShortMSA(df, target, cond, wt, bd); 28991cb0ef41Sopenharmony_ci } 29001cb0ef41Sopenharmony_ci } 29011cb0ef41Sopenharmony_ci } 29021cb0ef41Sopenharmony_ci} 29031cb0ef41Sopenharmony_ci 29041cb0ef41Sopenharmony_civoid TurboAssembler::BranchShortMSA(MSABranchDF df, Label* target, 29051cb0ef41Sopenharmony_ci MSABranchCondition cond, MSARegister wt, 29061cb0ef41Sopenharmony_ci BranchDelaySlot bd) { 29071cb0ef41Sopenharmony_ci if (IsEnabled(MIPS_SIMD)) { 29081cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 29091cb0ef41Sopenharmony_ci if (target) { 29101cb0ef41Sopenharmony_ci switch (cond) { 29111cb0ef41Sopenharmony_ci case all_not_zero: 29121cb0ef41Sopenharmony_ci switch (df) { 29131cb0ef41Sopenharmony_ci case MSA_BRANCH_D: 29141cb0ef41Sopenharmony_ci bnz_d(wt, target); 29151cb0ef41Sopenharmony_ci break; 29161cb0ef41Sopenharmony_ci case MSA_BRANCH_W: 29171cb0ef41Sopenharmony_ci bnz_w(wt, target); 29181cb0ef41Sopenharmony_ci break; 29191cb0ef41Sopenharmony_ci case MSA_BRANCH_H: 29201cb0ef41Sopenharmony_ci bnz_h(wt, target); 29211cb0ef41Sopenharmony_ci break; 29221cb0ef41Sopenharmony_ci case MSA_BRANCH_B: 29231cb0ef41Sopenharmony_ci default: 29241cb0ef41Sopenharmony_ci bnz_b(wt, target); 29251cb0ef41Sopenharmony_ci } 29261cb0ef41Sopenharmony_ci break; 29271cb0ef41Sopenharmony_ci case one_elem_not_zero: 29281cb0ef41Sopenharmony_ci bnz_v(wt, target); 29291cb0ef41Sopenharmony_ci break; 29301cb0ef41Sopenharmony_ci case one_elem_zero: 29311cb0ef41Sopenharmony_ci switch (df) { 29321cb0ef41Sopenharmony_ci case MSA_BRANCH_D: 29331cb0ef41Sopenharmony_ci bz_d(wt, target); 29341cb0ef41Sopenharmony_ci break; 29351cb0ef41Sopenharmony_ci case MSA_BRANCH_W: 29361cb0ef41Sopenharmony_ci bz_w(wt, target); 29371cb0ef41Sopenharmony_ci break; 29381cb0ef41Sopenharmony_ci case MSA_BRANCH_H: 29391cb0ef41Sopenharmony_ci bz_h(wt, target); 29401cb0ef41Sopenharmony_ci break; 29411cb0ef41Sopenharmony_ci case MSA_BRANCH_B: 29421cb0ef41Sopenharmony_ci default: 29431cb0ef41Sopenharmony_ci bz_b(wt, target); 29441cb0ef41Sopenharmony_ci } 29451cb0ef41Sopenharmony_ci break; 29461cb0ef41Sopenharmony_ci case all_zero: 29471cb0ef41Sopenharmony_ci bz_v(wt, target); 29481cb0ef41Sopenharmony_ci break; 29491cb0ef41Sopenharmony_ci default: 29501cb0ef41Sopenharmony_ci UNREACHABLE(); 29511cb0ef41Sopenharmony_ci } 29521cb0ef41Sopenharmony_ci } 29531cb0ef41Sopenharmony_ci } else { 29541cb0ef41Sopenharmony_ci UNREACHABLE(); 29551cb0ef41Sopenharmony_ci } 29561cb0ef41Sopenharmony_ci if (bd == PROTECT) { 29571cb0ef41Sopenharmony_ci nop(); 29581cb0ef41Sopenharmony_ci } 29591cb0ef41Sopenharmony_ci} 29601cb0ef41Sopenharmony_ci 29611cb0ef41Sopenharmony_civoid TurboAssembler::FmoveLow(FPURegister dst, Register src_low) { 29621cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 29631cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 29641cb0ef41Sopenharmony_ci DCHECK(src_low != scratch); 29651cb0ef41Sopenharmony_ci mfhc1(scratch, dst); 29661cb0ef41Sopenharmony_ci mtc1(src_low, dst); 29671cb0ef41Sopenharmony_ci mthc1(scratch, dst); 29681cb0ef41Sopenharmony_ci} 29691cb0ef41Sopenharmony_ci 29701cb0ef41Sopenharmony_civoid TurboAssembler::Move(FPURegister dst, uint32_t src) { 29711cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 29721cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 29731cb0ef41Sopenharmony_ci li(scratch, Operand(static_cast<int32_t>(src))); 29741cb0ef41Sopenharmony_ci mtc1(scratch, dst); 29751cb0ef41Sopenharmony_ci} 29761cb0ef41Sopenharmony_ci 29771cb0ef41Sopenharmony_civoid TurboAssembler::Move(FPURegister dst, uint64_t src) { 29781cb0ef41Sopenharmony_ci // Handle special values first. 29791cb0ef41Sopenharmony_ci if (src == bit_cast<uint64_t>(0.0) && has_double_zero_reg_set_) { 29801cb0ef41Sopenharmony_ci mov_d(dst, kDoubleRegZero); 29811cb0ef41Sopenharmony_ci } else if (src == bit_cast<uint64_t>(-0.0) && has_double_zero_reg_set_) { 29821cb0ef41Sopenharmony_ci Neg_d(dst, kDoubleRegZero); 29831cb0ef41Sopenharmony_ci } else { 29841cb0ef41Sopenharmony_ci uint32_t lo = src & 0xFFFFFFFF; 29851cb0ef41Sopenharmony_ci uint32_t hi = src >> 32; 29861cb0ef41Sopenharmony_ci // Move the low part of the double into the lower of the corresponding FPU 29871cb0ef41Sopenharmony_ci // register of FPU register pair. 29881cb0ef41Sopenharmony_ci if (lo != 0) { 29891cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 29901cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 29911cb0ef41Sopenharmony_ci li(scratch, Operand(lo)); 29921cb0ef41Sopenharmony_ci mtc1(scratch, dst); 29931cb0ef41Sopenharmony_ci } else { 29941cb0ef41Sopenharmony_ci mtc1(zero_reg, dst); 29951cb0ef41Sopenharmony_ci } 29961cb0ef41Sopenharmony_ci // Move the high part of the double into the higher of the corresponding FPU 29971cb0ef41Sopenharmony_ci // register of FPU register pair. 29981cb0ef41Sopenharmony_ci if (hi != 0) { 29991cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 30001cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 30011cb0ef41Sopenharmony_ci li(scratch, Operand(hi)); 30021cb0ef41Sopenharmony_ci mthc1(scratch, dst); 30031cb0ef41Sopenharmony_ci } else { 30041cb0ef41Sopenharmony_ci mthc1(zero_reg, dst); 30051cb0ef41Sopenharmony_ci } 30061cb0ef41Sopenharmony_ci if (dst == kDoubleRegZero) has_double_zero_reg_set_ = true; 30071cb0ef41Sopenharmony_ci } 30081cb0ef41Sopenharmony_ci} 30091cb0ef41Sopenharmony_ci 30101cb0ef41Sopenharmony_civoid TurboAssembler::Movz(Register rd, Register rs, Register rt) { 30111cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 30121cb0ef41Sopenharmony_ci Label done; 30131cb0ef41Sopenharmony_ci Branch(&done, ne, rt, Operand(zero_reg)); 30141cb0ef41Sopenharmony_ci mov(rd, rs); 30151cb0ef41Sopenharmony_ci bind(&done); 30161cb0ef41Sopenharmony_ci } else { 30171cb0ef41Sopenharmony_ci movz(rd, rs, rt); 30181cb0ef41Sopenharmony_ci } 30191cb0ef41Sopenharmony_ci} 30201cb0ef41Sopenharmony_ci 30211cb0ef41Sopenharmony_civoid TurboAssembler::Movn(Register rd, Register rs, Register rt) { 30221cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 30231cb0ef41Sopenharmony_ci Label done; 30241cb0ef41Sopenharmony_ci Branch(&done, eq, rt, Operand(zero_reg)); 30251cb0ef41Sopenharmony_ci mov(rd, rs); 30261cb0ef41Sopenharmony_ci bind(&done); 30271cb0ef41Sopenharmony_ci } else { 30281cb0ef41Sopenharmony_ci movn(rd, rs, rt); 30291cb0ef41Sopenharmony_ci } 30301cb0ef41Sopenharmony_ci} 30311cb0ef41Sopenharmony_ci 30321cb0ef41Sopenharmony_civoid TurboAssembler::LoadZeroOnCondition(Register rd, Register rs, 30331cb0ef41Sopenharmony_ci const Operand& rt, Condition cond) { 30341cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 30351cb0ef41Sopenharmony_ci switch (cond) { 30361cb0ef41Sopenharmony_ci case cc_always: 30371cb0ef41Sopenharmony_ci mov(rd, zero_reg); 30381cb0ef41Sopenharmony_ci break; 30391cb0ef41Sopenharmony_ci case eq: 30401cb0ef41Sopenharmony_ci if (rs == zero_reg) { 30411cb0ef41Sopenharmony_ci if (rt.is_reg()) { 30421cb0ef41Sopenharmony_ci LoadZeroIfConditionZero(rd, rt.rm()); 30431cb0ef41Sopenharmony_ci } else { 30441cb0ef41Sopenharmony_ci if (rt.immediate() == 0) { 30451cb0ef41Sopenharmony_ci mov(rd, zero_reg); 30461cb0ef41Sopenharmony_ci } else { 30471cb0ef41Sopenharmony_ci nop(); 30481cb0ef41Sopenharmony_ci } 30491cb0ef41Sopenharmony_ci } 30501cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 30511cb0ef41Sopenharmony_ci LoadZeroIfConditionZero(rd, rs); 30521cb0ef41Sopenharmony_ci } else { 30531cb0ef41Sopenharmony_ci Dsubu(t9, rs, rt); 30541cb0ef41Sopenharmony_ci LoadZeroIfConditionZero(rd, t9); 30551cb0ef41Sopenharmony_ci } 30561cb0ef41Sopenharmony_ci break; 30571cb0ef41Sopenharmony_ci case ne: 30581cb0ef41Sopenharmony_ci if (rs == zero_reg) { 30591cb0ef41Sopenharmony_ci if (rt.is_reg()) { 30601cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(rd, rt.rm()); 30611cb0ef41Sopenharmony_ci } else { 30621cb0ef41Sopenharmony_ci if (rt.immediate() != 0) { 30631cb0ef41Sopenharmony_ci mov(rd, zero_reg); 30641cb0ef41Sopenharmony_ci } else { 30651cb0ef41Sopenharmony_ci nop(); 30661cb0ef41Sopenharmony_ci } 30671cb0ef41Sopenharmony_ci } 30681cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 30691cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(rd, rs); 30701cb0ef41Sopenharmony_ci } else { 30711cb0ef41Sopenharmony_ci Dsubu(t9, rs, rt); 30721cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(rd, t9); 30731cb0ef41Sopenharmony_ci } 30741cb0ef41Sopenharmony_ci break; 30751cb0ef41Sopenharmony_ci 30761cb0ef41Sopenharmony_ci // Signed comparison. 30771cb0ef41Sopenharmony_ci case greater: 30781cb0ef41Sopenharmony_ci Sgt(t9, rs, rt); 30791cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(rd, t9); 30801cb0ef41Sopenharmony_ci break; 30811cb0ef41Sopenharmony_ci case greater_equal: 30821cb0ef41Sopenharmony_ci Sge(t9, rs, rt); 30831cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(rd, t9); 30841cb0ef41Sopenharmony_ci // rs >= rt 30851cb0ef41Sopenharmony_ci break; 30861cb0ef41Sopenharmony_ci case less: 30871cb0ef41Sopenharmony_ci Slt(t9, rs, rt); 30881cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(rd, t9); 30891cb0ef41Sopenharmony_ci // rs < rt 30901cb0ef41Sopenharmony_ci break; 30911cb0ef41Sopenharmony_ci case less_equal: 30921cb0ef41Sopenharmony_ci Sle(t9, rs, rt); 30931cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(rd, t9); 30941cb0ef41Sopenharmony_ci // rs <= rt 30951cb0ef41Sopenharmony_ci break; 30961cb0ef41Sopenharmony_ci 30971cb0ef41Sopenharmony_ci // Unsigned comparison. 30981cb0ef41Sopenharmony_ci case Ugreater: 30991cb0ef41Sopenharmony_ci Sgtu(t9, rs, rt); 31001cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(rd, t9); 31011cb0ef41Sopenharmony_ci // rs > rt 31021cb0ef41Sopenharmony_ci break; 31031cb0ef41Sopenharmony_ci 31041cb0ef41Sopenharmony_ci case Ugreater_equal: 31051cb0ef41Sopenharmony_ci Sgeu(t9, rs, rt); 31061cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(rd, t9); 31071cb0ef41Sopenharmony_ci // rs >= rt 31081cb0ef41Sopenharmony_ci break; 31091cb0ef41Sopenharmony_ci case Uless: 31101cb0ef41Sopenharmony_ci Sltu(t9, rs, rt); 31111cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(rd, t9); 31121cb0ef41Sopenharmony_ci // rs < rt 31131cb0ef41Sopenharmony_ci break; 31141cb0ef41Sopenharmony_ci case Uless_equal: 31151cb0ef41Sopenharmony_ci Sleu(t9, rs, rt); 31161cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(rd, t9); 31171cb0ef41Sopenharmony_ci // rs <= rt 31181cb0ef41Sopenharmony_ci break; 31191cb0ef41Sopenharmony_ci default: 31201cb0ef41Sopenharmony_ci UNREACHABLE(); 31211cb0ef41Sopenharmony_ci } 31221cb0ef41Sopenharmony_ci} 31231cb0ef41Sopenharmony_ci 31241cb0ef41Sopenharmony_civoid TurboAssembler::LoadZeroIfConditionNotZero(Register dest, 31251cb0ef41Sopenharmony_ci Register condition) { 31261cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 31271cb0ef41Sopenharmony_ci seleqz(dest, dest, condition); 31281cb0ef41Sopenharmony_ci } else { 31291cb0ef41Sopenharmony_ci Movn(dest, zero_reg, condition); 31301cb0ef41Sopenharmony_ci } 31311cb0ef41Sopenharmony_ci} 31321cb0ef41Sopenharmony_ci 31331cb0ef41Sopenharmony_civoid TurboAssembler::LoadZeroIfConditionZero(Register dest, 31341cb0ef41Sopenharmony_ci Register condition) { 31351cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 31361cb0ef41Sopenharmony_ci selnez(dest, dest, condition); 31371cb0ef41Sopenharmony_ci } else { 31381cb0ef41Sopenharmony_ci Movz(dest, zero_reg, condition); 31391cb0ef41Sopenharmony_ci } 31401cb0ef41Sopenharmony_ci} 31411cb0ef41Sopenharmony_ci 31421cb0ef41Sopenharmony_civoid TurboAssembler::LoadZeroIfFPUCondition(Register dest) { 31431cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 31441cb0ef41Sopenharmony_ci dmfc1(kScratchReg, kDoubleCompareReg); 31451cb0ef41Sopenharmony_ci LoadZeroIfConditionNotZero(dest, kScratchReg); 31461cb0ef41Sopenharmony_ci } else { 31471cb0ef41Sopenharmony_ci Movt(dest, zero_reg); 31481cb0ef41Sopenharmony_ci } 31491cb0ef41Sopenharmony_ci} 31501cb0ef41Sopenharmony_ci 31511cb0ef41Sopenharmony_civoid TurboAssembler::LoadZeroIfNotFPUCondition(Register dest) { 31521cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 31531cb0ef41Sopenharmony_ci dmfc1(kScratchReg, kDoubleCompareReg); 31541cb0ef41Sopenharmony_ci LoadZeroIfConditionZero(dest, kScratchReg); 31551cb0ef41Sopenharmony_ci } else { 31561cb0ef41Sopenharmony_ci Movf(dest, zero_reg); 31571cb0ef41Sopenharmony_ci } 31581cb0ef41Sopenharmony_ci} 31591cb0ef41Sopenharmony_ci 31601cb0ef41Sopenharmony_civoid TurboAssembler::Movt(Register rd, Register rs, uint16_t cc) { 31611cb0ef41Sopenharmony_ci movt(rd, rs, cc); 31621cb0ef41Sopenharmony_ci} 31631cb0ef41Sopenharmony_ci 31641cb0ef41Sopenharmony_civoid TurboAssembler::Movf(Register rd, Register rs, uint16_t cc) { 31651cb0ef41Sopenharmony_ci movf(rd, rs, cc); 31661cb0ef41Sopenharmony_ci} 31671cb0ef41Sopenharmony_ci 31681cb0ef41Sopenharmony_civoid TurboAssembler::Clz(Register rd, Register rs) { clz(rd, rs); } 31691cb0ef41Sopenharmony_ci 31701cb0ef41Sopenharmony_civoid TurboAssembler::Dclz(Register rd, Register rs) { dclz(rd, rs); } 31711cb0ef41Sopenharmony_ci 31721cb0ef41Sopenharmony_civoid TurboAssembler::Ctz(Register rd, Register rs) { 31731cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 31741cb0ef41Sopenharmony_ci // We don't have an instruction to count the number of trailing zeroes. 31751cb0ef41Sopenharmony_ci // Start by flipping the bits end-for-end so we can count the number of 31761cb0ef41Sopenharmony_ci // leading zeroes instead. 31771cb0ef41Sopenharmony_ci rotr(rd, rs, 16); 31781cb0ef41Sopenharmony_ci wsbh(rd, rd); 31791cb0ef41Sopenharmony_ci bitswap(rd, rd); 31801cb0ef41Sopenharmony_ci Clz(rd, rd); 31811cb0ef41Sopenharmony_ci } else { 31821cb0ef41Sopenharmony_ci // Convert trailing zeroes to trailing ones, and bits to their left 31831cb0ef41Sopenharmony_ci // to zeroes. 31841cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 31851cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 31861cb0ef41Sopenharmony_ci Daddu(scratch, rs, -1); 31871cb0ef41Sopenharmony_ci Xor(rd, scratch, rs); 31881cb0ef41Sopenharmony_ci And(rd, rd, scratch); 31891cb0ef41Sopenharmony_ci // Count number of leading zeroes. 31901cb0ef41Sopenharmony_ci Clz(rd, rd); 31911cb0ef41Sopenharmony_ci // Subtract number of leading zeroes from 32 to get number of trailing 31921cb0ef41Sopenharmony_ci // ones. Remember that the trailing ones were formerly trailing zeroes. 31931cb0ef41Sopenharmony_ci li(scratch, 32); 31941cb0ef41Sopenharmony_ci Subu(rd, scratch, rd); 31951cb0ef41Sopenharmony_ci } 31961cb0ef41Sopenharmony_ci} 31971cb0ef41Sopenharmony_ci 31981cb0ef41Sopenharmony_civoid TurboAssembler::Dctz(Register rd, Register rs) { 31991cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 32001cb0ef41Sopenharmony_ci // We don't have an instruction to count the number of trailing zeroes. 32011cb0ef41Sopenharmony_ci // Start by flipping the bits end-for-end so we can count the number of 32021cb0ef41Sopenharmony_ci // leading zeroes instead. 32031cb0ef41Sopenharmony_ci dsbh(rd, rs); 32041cb0ef41Sopenharmony_ci dshd(rd, rd); 32051cb0ef41Sopenharmony_ci dbitswap(rd, rd); 32061cb0ef41Sopenharmony_ci dclz(rd, rd); 32071cb0ef41Sopenharmony_ci } else { 32081cb0ef41Sopenharmony_ci // Convert trailing zeroes to trailing ones, and bits to their left 32091cb0ef41Sopenharmony_ci // to zeroes. 32101cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 32111cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 32121cb0ef41Sopenharmony_ci Daddu(scratch, rs, -1); 32131cb0ef41Sopenharmony_ci Xor(rd, scratch, rs); 32141cb0ef41Sopenharmony_ci And(rd, rd, scratch); 32151cb0ef41Sopenharmony_ci // Count number of leading zeroes. 32161cb0ef41Sopenharmony_ci dclz(rd, rd); 32171cb0ef41Sopenharmony_ci // Subtract number of leading zeroes from 64 to get number of trailing 32181cb0ef41Sopenharmony_ci // ones. Remember that the trailing ones were formerly trailing zeroes. 32191cb0ef41Sopenharmony_ci li(scratch, 64); 32201cb0ef41Sopenharmony_ci Dsubu(rd, scratch, rd); 32211cb0ef41Sopenharmony_ci } 32221cb0ef41Sopenharmony_ci} 32231cb0ef41Sopenharmony_ci 32241cb0ef41Sopenharmony_civoid TurboAssembler::Popcnt(Register rd, Register rs) { 32251cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 32261cb0ef41Sopenharmony_ci // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel 32271cb0ef41Sopenharmony_ci // 32281cb0ef41Sopenharmony_ci // A generalization of the best bit counting method to integers of 32291cb0ef41Sopenharmony_ci // bit-widths up to 128 (parameterized by type T) is this: 32301cb0ef41Sopenharmony_ci // 32311cb0ef41Sopenharmony_ci // v = v - ((v >> 1) & (T)~(T)0/3); // temp 32321cb0ef41Sopenharmony_ci // v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3); // temp 32331cb0ef41Sopenharmony_ci // v = (v + (v >> 4)) & (T)~(T)0/255*15; // temp 32341cb0ef41Sopenharmony_ci // c = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * BITS_PER_BYTE; //count 32351cb0ef41Sopenharmony_ci // 32361cb0ef41Sopenharmony_ci // For comparison, for 32-bit quantities, this algorithm can be executed 32371cb0ef41Sopenharmony_ci // using 20 MIPS instructions (the calls to LoadConst32() generate two 32381cb0ef41Sopenharmony_ci // machine instructions each for the values being used in this algorithm). 32391cb0ef41Sopenharmony_ci // A(n unrolled) loop-based algorithm requires 25 instructions. 32401cb0ef41Sopenharmony_ci // 32411cb0ef41Sopenharmony_ci // For a 64-bit operand this can be performed in 24 instructions compared 32421cb0ef41Sopenharmony_ci // to a(n unrolled) loop based algorithm which requires 38 instructions. 32431cb0ef41Sopenharmony_ci // 32441cb0ef41Sopenharmony_ci // There are algorithms which are faster in the cases where very few 32451cb0ef41Sopenharmony_ci // bits are set but the algorithm here attempts to minimize the total 32461cb0ef41Sopenharmony_ci // number of instructions executed even when a large number of bits 32471cb0ef41Sopenharmony_ci // are set. 32481cb0ef41Sopenharmony_ci uint32_t B0 = 0x55555555; // (T)~(T)0/3 32491cb0ef41Sopenharmony_ci uint32_t B1 = 0x33333333; // (T)~(T)0/15*3 32501cb0ef41Sopenharmony_ci uint32_t B2 = 0x0F0F0F0F; // (T)~(T)0/255*15 32511cb0ef41Sopenharmony_ci uint32_t value = 0x01010101; // (T)~(T)0/255 32521cb0ef41Sopenharmony_ci uint32_t shift = 24; // (sizeof(T) - 1) * BITS_PER_BYTE 32531cb0ef41Sopenharmony_ci 32541cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 32551cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 32561cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 32571cb0ef41Sopenharmony_ci Register scratch2 = t8; 32581cb0ef41Sopenharmony_ci srl(scratch, rs, 1); 32591cb0ef41Sopenharmony_ci li(scratch2, B0); 32601cb0ef41Sopenharmony_ci And(scratch, scratch, scratch2); 32611cb0ef41Sopenharmony_ci Subu(scratch, rs, scratch); 32621cb0ef41Sopenharmony_ci li(scratch2, B1); 32631cb0ef41Sopenharmony_ci And(rd, scratch, scratch2); 32641cb0ef41Sopenharmony_ci srl(scratch, scratch, 2); 32651cb0ef41Sopenharmony_ci And(scratch, scratch, scratch2); 32661cb0ef41Sopenharmony_ci Addu(scratch, rd, scratch); 32671cb0ef41Sopenharmony_ci srl(rd, scratch, 4); 32681cb0ef41Sopenharmony_ci Addu(rd, rd, scratch); 32691cb0ef41Sopenharmony_ci li(scratch2, B2); 32701cb0ef41Sopenharmony_ci And(rd, rd, scratch2); 32711cb0ef41Sopenharmony_ci li(scratch, value); 32721cb0ef41Sopenharmony_ci Mul(rd, rd, scratch); 32731cb0ef41Sopenharmony_ci srl(rd, rd, shift); 32741cb0ef41Sopenharmony_ci} 32751cb0ef41Sopenharmony_ci 32761cb0ef41Sopenharmony_civoid TurboAssembler::Dpopcnt(Register rd, Register rs) { 32771cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 32781cb0ef41Sopenharmony_ci uint64_t B0 = 0x5555555555555555l; // (T)~(T)0/3 32791cb0ef41Sopenharmony_ci uint64_t B1 = 0x3333333333333333l; // (T)~(T)0/15*3 32801cb0ef41Sopenharmony_ci uint64_t B2 = 0x0F0F0F0F0F0F0F0Fl; // (T)~(T)0/255*15 32811cb0ef41Sopenharmony_ci uint64_t value = 0x0101010101010101l; // (T)~(T)0/255 32821cb0ef41Sopenharmony_ci uint64_t shift = 24; // (sizeof(T) - 1) * BITS_PER_BYTE 32831cb0ef41Sopenharmony_ci 32841cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 32851cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 32861cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 32871cb0ef41Sopenharmony_ci Register scratch2 = t8; 32881cb0ef41Sopenharmony_ci dsrl(scratch, rs, 1); 32891cb0ef41Sopenharmony_ci li(scratch2, B0); 32901cb0ef41Sopenharmony_ci And(scratch, scratch, scratch2); 32911cb0ef41Sopenharmony_ci Dsubu(scratch, rs, scratch); 32921cb0ef41Sopenharmony_ci li(scratch2, B1); 32931cb0ef41Sopenharmony_ci And(rd, scratch, scratch2); 32941cb0ef41Sopenharmony_ci dsrl(scratch, scratch, 2); 32951cb0ef41Sopenharmony_ci And(scratch, scratch, scratch2); 32961cb0ef41Sopenharmony_ci Daddu(scratch, rd, scratch); 32971cb0ef41Sopenharmony_ci dsrl(rd, scratch, 4); 32981cb0ef41Sopenharmony_ci Daddu(rd, rd, scratch); 32991cb0ef41Sopenharmony_ci li(scratch2, B2); 33001cb0ef41Sopenharmony_ci And(rd, rd, scratch2); 33011cb0ef41Sopenharmony_ci li(scratch, value); 33021cb0ef41Sopenharmony_ci Dmul(rd, rd, scratch); 33031cb0ef41Sopenharmony_ci dsrl32(rd, rd, shift); 33041cb0ef41Sopenharmony_ci} 33051cb0ef41Sopenharmony_ci 33061cb0ef41Sopenharmony_civoid TurboAssembler::TryInlineTruncateDoubleToI(Register result, 33071cb0ef41Sopenharmony_ci DoubleRegister double_input, 33081cb0ef41Sopenharmony_ci Label* done) { 33091cb0ef41Sopenharmony_ci DoubleRegister single_scratch = kScratchDoubleReg.low(); 33101cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 33111cb0ef41Sopenharmony_ci Register scratch = t9; 33121cb0ef41Sopenharmony_ci 33131cb0ef41Sopenharmony_ci // Try a conversion to a signed integer. 33141cb0ef41Sopenharmony_ci trunc_w_d(single_scratch, double_input); 33151cb0ef41Sopenharmony_ci mfc1(result, single_scratch); 33161cb0ef41Sopenharmony_ci // Retrieve the FCSR. 33171cb0ef41Sopenharmony_ci cfc1(scratch, FCSR); 33181cb0ef41Sopenharmony_ci // Check for overflow and NaNs. 33191cb0ef41Sopenharmony_ci And(scratch, scratch, 33201cb0ef41Sopenharmony_ci kFCSROverflowCauseMask | kFCSRUnderflowCauseMask | 33211cb0ef41Sopenharmony_ci kFCSRInvalidOpCauseMask); 33221cb0ef41Sopenharmony_ci // If we had no exceptions we are done. 33231cb0ef41Sopenharmony_ci Branch(done, eq, scratch, Operand(zero_reg)); 33241cb0ef41Sopenharmony_ci} 33251cb0ef41Sopenharmony_ci 33261cb0ef41Sopenharmony_civoid TurboAssembler::TruncateDoubleToI(Isolate* isolate, Zone* zone, 33271cb0ef41Sopenharmony_ci Register result, 33281cb0ef41Sopenharmony_ci DoubleRegister double_input, 33291cb0ef41Sopenharmony_ci StubCallMode stub_mode) { 33301cb0ef41Sopenharmony_ci Label done; 33311cb0ef41Sopenharmony_ci 33321cb0ef41Sopenharmony_ci TryInlineTruncateDoubleToI(result, double_input, &done); 33331cb0ef41Sopenharmony_ci 33341cb0ef41Sopenharmony_ci // If we fell through then inline version didn't succeed - call stub instead. 33351cb0ef41Sopenharmony_ci push(ra); 33361cb0ef41Sopenharmony_ci Dsubu(sp, sp, Operand(kDoubleSize)); // Put input on stack. 33371cb0ef41Sopenharmony_ci Sdc1(double_input, MemOperand(sp, 0)); 33381cb0ef41Sopenharmony_ci 33391cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 33401cb0ef41Sopenharmony_ci if (stub_mode == StubCallMode::kCallWasmRuntimeStub) { 33411cb0ef41Sopenharmony_ci Call(wasm::WasmCode::kDoubleToI, RelocInfo::WASM_STUB_CALL); 33421cb0ef41Sopenharmony_ci#else 33431cb0ef41Sopenharmony_ci // For balance. 33441cb0ef41Sopenharmony_ci if (false) { 33451cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 33461cb0ef41Sopenharmony_ci } else { 33471cb0ef41Sopenharmony_ci Call(BUILTIN_CODE(isolate, DoubleToI), RelocInfo::CODE_TARGET); 33481cb0ef41Sopenharmony_ci } 33491cb0ef41Sopenharmony_ci Ld(result, MemOperand(sp, 0)); 33501cb0ef41Sopenharmony_ci 33511cb0ef41Sopenharmony_ci Daddu(sp, sp, Operand(kDoubleSize)); 33521cb0ef41Sopenharmony_ci pop(ra); 33531cb0ef41Sopenharmony_ci 33541cb0ef41Sopenharmony_ci bind(&done); 33551cb0ef41Sopenharmony_ci} 33561cb0ef41Sopenharmony_ci 33571cb0ef41Sopenharmony_ci// Emulated condtional branches do not emit a nop in the branch delay slot. 33581cb0ef41Sopenharmony_ci// 33591cb0ef41Sopenharmony_ci// BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. 33601cb0ef41Sopenharmony_ci#define BRANCH_ARGS_CHECK(cond, rs, rt) \ 33611cb0ef41Sopenharmony_ci DCHECK((cond == cc_always && rs == zero_reg && rt.rm() == zero_reg) || \ 33621cb0ef41Sopenharmony_ci (cond != cc_always && (rs != zero_reg || rt.rm() != zero_reg))) 33631cb0ef41Sopenharmony_ci 33641cb0ef41Sopenharmony_civoid TurboAssembler::Branch(int32_t offset, BranchDelaySlot bdslot) { 33651cb0ef41Sopenharmony_ci DCHECK_EQ(kArchVariant, kMips64r6 ? is_int26(offset) : is_int16(offset)); 33661cb0ef41Sopenharmony_ci BranchShort(offset, bdslot); 33671cb0ef41Sopenharmony_ci} 33681cb0ef41Sopenharmony_ci 33691cb0ef41Sopenharmony_civoid TurboAssembler::Branch(int32_t offset, Condition cond, Register rs, 33701cb0ef41Sopenharmony_ci const Operand& rt, BranchDelaySlot bdslot) { 33711cb0ef41Sopenharmony_ci bool is_near = BranchShortCheck(offset, nullptr, cond, rs, rt, bdslot); 33721cb0ef41Sopenharmony_ci DCHECK(is_near); 33731cb0ef41Sopenharmony_ci USE(is_near); 33741cb0ef41Sopenharmony_ci} 33751cb0ef41Sopenharmony_ci 33761cb0ef41Sopenharmony_civoid TurboAssembler::Branch(Label* L, BranchDelaySlot bdslot) { 33771cb0ef41Sopenharmony_ci if (L->is_bound()) { 33781cb0ef41Sopenharmony_ci if (is_near_branch(L)) { 33791cb0ef41Sopenharmony_ci BranchShort(L, bdslot); 33801cb0ef41Sopenharmony_ci } else { 33811cb0ef41Sopenharmony_ci BranchLong(L, bdslot); 33821cb0ef41Sopenharmony_ci } 33831cb0ef41Sopenharmony_ci } else { 33841cb0ef41Sopenharmony_ci if (is_trampoline_emitted()) { 33851cb0ef41Sopenharmony_ci BranchLong(L, bdslot); 33861cb0ef41Sopenharmony_ci } else { 33871cb0ef41Sopenharmony_ci BranchShort(L, bdslot); 33881cb0ef41Sopenharmony_ci } 33891cb0ef41Sopenharmony_ci } 33901cb0ef41Sopenharmony_ci} 33911cb0ef41Sopenharmony_ci 33921cb0ef41Sopenharmony_civoid TurboAssembler::Branch(Label* L, Condition cond, Register rs, 33931cb0ef41Sopenharmony_ci const Operand& rt, BranchDelaySlot bdslot) { 33941cb0ef41Sopenharmony_ci if (L->is_bound()) { 33951cb0ef41Sopenharmony_ci if (!BranchShortCheck(0, L, cond, rs, rt, bdslot)) { 33961cb0ef41Sopenharmony_ci if (cond != cc_always) { 33971cb0ef41Sopenharmony_ci Label skip; 33981cb0ef41Sopenharmony_ci Condition neg_cond = NegateCondition(cond); 33991cb0ef41Sopenharmony_ci BranchShort(&skip, neg_cond, rs, rt); 34001cb0ef41Sopenharmony_ci BranchLong(L, bdslot); 34011cb0ef41Sopenharmony_ci bind(&skip); 34021cb0ef41Sopenharmony_ci } else { 34031cb0ef41Sopenharmony_ci BranchLong(L, bdslot); 34041cb0ef41Sopenharmony_ci } 34051cb0ef41Sopenharmony_ci } 34061cb0ef41Sopenharmony_ci } else { 34071cb0ef41Sopenharmony_ci if (is_trampoline_emitted()) { 34081cb0ef41Sopenharmony_ci if (cond != cc_always) { 34091cb0ef41Sopenharmony_ci Label skip; 34101cb0ef41Sopenharmony_ci Condition neg_cond = NegateCondition(cond); 34111cb0ef41Sopenharmony_ci BranchShort(&skip, neg_cond, rs, rt); 34121cb0ef41Sopenharmony_ci BranchLong(L, bdslot); 34131cb0ef41Sopenharmony_ci bind(&skip); 34141cb0ef41Sopenharmony_ci } else { 34151cb0ef41Sopenharmony_ci BranchLong(L, bdslot); 34161cb0ef41Sopenharmony_ci } 34171cb0ef41Sopenharmony_ci } else { 34181cb0ef41Sopenharmony_ci BranchShort(L, cond, rs, rt, bdslot); 34191cb0ef41Sopenharmony_ci } 34201cb0ef41Sopenharmony_ci } 34211cb0ef41Sopenharmony_ci} 34221cb0ef41Sopenharmony_ci 34231cb0ef41Sopenharmony_civoid TurboAssembler::Branch(Label* L, Condition cond, Register rs, 34241cb0ef41Sopenharmony_ci RootIndex index, BranchDelaySlot bdslot) { 34251cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 34261cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 34271cb0ef41Sopenharmony_ci LoadRoot(scratch, index); 34281cb0ef41Sopenharmony_ci Branch(L, cond, rs, Operand(scratch), bdslot); 34291cb0ef41Sopenharmony_ci} 34301cb0ef41Sopenharmony_ci 34311cb0ef41Sopenharmony_civoid TurboAssembler::BranchShortHelper(int16_t offset, Label* L, 34321cb0ef41Sopenharmony_ci BranchDelaySlot bdslot) { 34331cb0ef41Sopenharmony_ci DCHECK(L == nullptr || offset == 0); 34341cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 34351cb0ef41Sopenharmony_ci b(offset); 34361cb0ef41Sopenharmony_ci 34371cb0ef41Sopenharmony_ci // Emit a nop in the branch delay slot if required. 34381cb0ef41Sopenharmony_ci if (bdslot == PROTECT) nop(); 34391cb0ef41Sopenharmony_ci} 34401cb0ef41Sopenharmony_ci 34411cb0ef41Sopenharmony_civoid TurboAssembler::BranchShortHelperR6(int32_t offset, Label* L) { 34421cb0ef41Sopenharmony_ci DCHECK(L == nullptr || offset == 0); 34431cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset26); 34441cb0ef41Sopenharmony_ci bc(offset); 34451cb0ef41Sopenharmony_ci} 34461cb0ef41Sopenharmony_ci 34471cb0ef41Sopenharmony_civoid TurboAssembler::BranchShort(int32_t offset, BranchDelaySlot bdslot) { 34481cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bdslot == PROTECT) { 34491cb0ef41Sopenharmony_ci DCHECK(is_int26(offset)); 34501cb0ef41Sopenharmony_ci BranchShortHelperR6(offset, nullptr); 34511cb0ef41Sopenharmony_ci } else { 34521cb0ef41Sopenharmony_ci DCHECK(is_int16(offset)); 34531cb0ef41Sopenharmony_ci BranchShortHelper(offset, nullptr, bdslot); 34541cb0ef41Sopenharmony_ci } 34551cb0ef41Sopenharmony_ci} 34561cb0ef41Sopenharmony_ci 34571cb0ef41Sopenharmony_civoid TurboAssembler::BranchShort(Label* L, BranchDelaySlot bdslot) { 34581cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bdslot == PROTECT) { 34591cb0ef41Sopenharmony_ci BranchShortHelperR6(0, L); 34601cb0ef41Sopenharmony_ci } else { 34611cb0ef41Sopenharmony_ci BranchShortHelper(0, L, bdslot); 34621cb0ef41Sopenharmony_ci } 34631cb0ef41Sopenharmony_ci} 34641cb0ef41Sopenharmony_ci 34651cb0ef41Sopenharmony_ciint32_t TurboAssembler::GetOffset(int32_t offset, Label* L, OffsetSize bits) { 34661cb0ef41Sopenharmony_ci if (L) { 34671cb0ef41Sopenharmony_ci offset = branch_offset_helper(L, bits) >> 2; 34681cb0ef41Sopenharmony_ci } else { 34691cb0ef41Sopenharmony_ci DCHECK(is_intn(offset, bits)); 34701cb0ef41Sopenharmony_ci } 34711cb0ef41Sopenharmony_ci return offset; 34721cb0ef41Sopenharmony_ci} 34731cb0ef41Sopenharmony_ci 34741cb0ef41Sopenharmony_ciRegister TurboAssembler::GetRtAsRegisterHelper(const Operand& rt, 34751cb0ef41Sopenharmony_ci Register scratch) { 34761cb0ef41Sopenharmony_ci Register r2 = no_reg; 34771cb0ef41Sopenharmony_ci if (rt.is_reg()) { 34781cb0ef41Sopenharmony_ci r2 = rt.rm(); 34791cb0ef41Sopenharmony_ci } else { 34801cb0ef41Sopenharmony_ci r2 = scratch; 34811cb0ef41Sopenharmony_ci li(r2, rt); 34821cb0ef41Sopenharmony_ci } 34831cb0ef41Sopenharmony_ci 34841cb0ef41Sopenharmony_ci return r2; 34851cb0ef41Sopenharmony_ci} 34861cb0ef41Sopenharmony_ci 34871cb0ef41Sopenharmony_cibool TurboAssembler::CalculateOffset(Label* L, int32_t* offset, 34881cb0ef41Sopenharmony_ci OffsetSize bits) { 34891cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 34901cb0ef41Sopenharmony_ci *offset = GetOffset(*offset, L, bits); 34911cb0ef41Sopenharmony_ci return true; 34921cb0ef41Sopenharmony_ci} 34931cb0ef41Sopenharmony_ci 34941cb0ef41Sopenharmony_cibool TurboAssembler::CalculateOffset(Label* L, int32_t* offset, OffsetSize bits, 34951cb0ef41Sopenharmony_ci Register* scratch, const Operand& rt) { 34961cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 34971cb0ef41Sopenharmony_ci *scratch = GetRtAsRegisterHelper(rt, *scratch); 34981cb0ef41Sopenharmony_ci *offset = GetOffset(*offset, L, bits); 34991cb0ef41Sopenharmony_ci return true; 35001cb0ef41Sopenharmony_ci} 35011cb0ef41Sopenharmony_ci 35021cb0ef41Sopenharmony_cibool TurboAssembler::BranchShortHelperR6(int32_t offset, Label* L, 35031cb0ef41Sopenharmony_ci Condition cond, Register rs, 35041cb0ef41Sopenharmony_ci const Operand& rt) { 35051cb0ef41Sopenharmony_ci DCHECK(L == nullptr || offset == 0); 35061cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 35071cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 35081cb0ef41Sopenharmony_ci Register scratch = temps.hasAvailable() ? temps.Acquire() : t8; 35091cb0ef41Sopenharmony_ci 35101cb0ef41Sopenharmony_ci // Be careful to always use shifted_branch_offset only just before the 35111cb0ef41Sopenharmony_ci // branch instruction, as the location will be remember for patching the 35121cb0ef41Sopenharmony_ci // target. 35131cb0ef41Sopenharmony_ci { 35141cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 35151cb0ef41Sopenharmony_ci switch (cond) { 35161cb0ef41Sopenharmony_ci case cc_always: 35171cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset26)) return false; 35181cb0ef41Sopenharmony_ci bc(offset); 35191cb0ef41Sopenharmony_ci break; 35201cb0ef41Sopenharmony_ci case eq: 35211cb0ef41Sopenharmony_ci if (rt.is_reg() && rs.code() == rt.rm().code()) { 35221cb0ef41Sopenharmony_ci // Pre R6 beq is used here to make the code patchable. Otherwise bc 35231cb0ef41Sopenharmony_ci // should be used which has no condition field so is not patchable. 35241cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 35251cb0ef41Sopenharmony_ci return false; 35261cb0ef41Sopenharmony_ci beq(rs, scratch, offset); 35271cb0ef41Sopenharmony_ci nop(); 35281cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 35291cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset21)) return false; 35301cb0ef41Sopenharmony_ci beqzc(rs, offset); 35311cb0ef41Sopenharmony_ci } else { 35321cb0ef41Sopenharmony_ci // We don't want any other register but scratch clobbered. 35331cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 35341cb0ef41Sopenharmony_ci return false; 35351cb0ef41Sopenharmony_ci beqc(rs, scratch, offset); 35361cb0ef41Sopenharmony_ci } 35371cb0ef41Sopenharmony_ci break; 35381cb0ef41Sopenharmony_ci case ne: 35391cb0ef41Sopenharmony_ci if (rt.is_reg() && rs.code() == rt.rm().code()) { 35401cb0ef41Sopenharmony_ci // Pre R6 bne is used here to make the code patchable. Otherwise we 35411cb0ef41Sopenharmony_ci // should not generate any instruction. 35421cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 35431cb0ef41Sopenharmony_ci return false; 35441cb0ef41Sopenharmony_ci bne(rs, scratch, offset); 35451cb0ef41Sopenharmony_ci nop(); 35461cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 35471cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset21)) return false; 35481cb0ef41Sopenharmony_ci bnezc(rs, offset); 35491cb0ef41Sopenharmony_ci } else { 35501cb0ef41Sopenharmony_ci // We don't want any other register but scratch clobbered. 35511cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 35521cb0ef41Sopenharmony_ci return false; 35531cb0ef41Sopenharmony_ci bnec(rs, scratch, offset); 35541cb0ef41Sopenharmony_ci } 35551cb0ef41Sopenharmony_ci break; 35561cb0ef41Sopenharmony_ci 35571cb0ef41Sopenharmony_ci // Signed comparison. 35581cb0ef41Sopenharmony_ci case greater: 35591cb0ef41Sopenharmony_ci // rs > rt 35601cb0ef41Sopenharmony_ci if (rt.is_reg() && rs.code() == rt.rm().code()) { 35611cb0ef41Sopenharmony_ci break; // No code needs to be emitted. 35621cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 35631cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 35641cb0ef41Sopenharmony_ci return false; 35651cb0ef41Sopenharmony_ci bltzc(scratch, offset); 35661cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 35671cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16)) return false; 35681cb0ef41Sopenharmony_ci bgtzc(rs, offset); 35691cb0ef41Sopenharmony_ci } else { 35701cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 35711cb0ef41Sopenharmony_ci return false; 35721cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 35731cb0ef41Sopenharmony_ci bltc(scratch, rs, offset); 35741cb0ef41Sopenharmony_ci } 35751cb0ef41Sopenharmony_ci break; 35761cb0ef41Sopenharmony_ci case greater_equal: 35771cb0ef41Sopenharmony_ci // rs >= rt 35781cb0ef41Sopenharmony_ci if (rt.is_reg() && rs.code() == rt.rm().code()) { 35791cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset26)) return false; 35801cb0ef41Sopenharmony_ci bc(offset); 35811cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 35821cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 35831cb0ef41Sopenharmony_ci return false; 35841cb0ef41Sopenharmony_ci blezc(scratch, offset); 35851cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 35861cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16)) return false; 35871cb0ef41Sopenharmony_ci bgezc(rs, offset); 35881cb0ef41Sopenharmony_ci } else { 35891cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 35901cb0ef41Sopenharmony_ci return false; 35911cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 35921cb0ef41Sopenharmony_ci bgec(rs, scratch, offset); 35931cb0ef41Sopenharmony_ci } 35941cb0ef41Sopenharmony_ci break; 35951cb0ef41Sopenharmony_ci case less: 35961cb0ef41Sopenharmony_ci // rs < rt 35971cb0ef41Sopenharmony_ci if (rt.is_reg() && rs.code() == rt.rm().code()) { 35981cb0ef41Sopenharmony_ci break; // No code needs to be emitted. 35991cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 36001cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 36011cb0ef41Sopenharmony_ci return false; 36021cb0ef41Sopenharmony_ci bgtzc(scratch, offset); 36031cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 36041cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16)) return false; 36051cb0ef41Sopenharmony_ci bltzc(rs, offset); 36061cb0ef41Sopenharmony_ci } else { 36071cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 36081cb0ef41Sopenharmony_ci return false; 36091cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 36101cb0ef41Sopenharmony_ci bltc(rs, scratch, offset); 36111cb0ef41Sopenharmony_ci } 36121cb0ef41Sopenharmony_ci break; 36131cb0ef41Sopenharmony_ci case less_equal: 36141cb0ef41Sopenharmony_ci // rs <= rt 36151cb0ef41Sopenharmony_ci if (rt.is_reg() && rs.code() == rt.rm().code()) { 36161cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset26)) return false; 36171cb0ef41Sopenharmony_ci bc(offset); 36181cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 36191cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 36201cb0ef41Sopenharmony_ci return false; 36211cb0ef41Sopenharmony_ci bgezc(scratch, offset); 36221cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 36231cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16)) return false; 36241cb0ef41Sopenharmony_ci blezc(rs, offset); 36251cb0ef41Sopenharmony_ci } else { 36261cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 36271cb0ef41Sopenharmony_ci return false; 36281cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 36291cb0ef41Sopenharmony_ci bgec(scratch, rs, offset); 36301cb0ef41Sopenharmony_ci } 36311cb0ef41Sopenharmony_ci break; 36321cb0ef41Sopenharmony_ci 36331cb0ef41Sopenharmony_ci // Unsigned comparison. 36341cb0ef41Sopenharmony_ci case Ugreater: 36351cb0ef41Sopenharmony_ci // rs > rt 36361cb0ef41Sopenharmony_ci if (rt.is_reg() && rs.code() == rt.rm().code()) { 36371cb0ef41Sopenharmony_ci break; // No code needs to be emitted. 36381cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 36391cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset21, &scratch, rt)) 36401cb0ef41Sopenharmony_ci return false; 36411cb0ef41Sopenharmony_ci bnezc(scratch, offset); 36421cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 36431cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset21)) return false; 36441cb0ef41Sopenharmony_ci bnezc(rs, offset); 36451cb0ef41Sopenharmony_ci } else { 36461cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 36471cb0ef41Sopenharmony_ci return false; 36481cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 36491cb0ef41Sopenharmony_ci bltuc(scratch, rs, offset); 36501cb0ef41Sopenharmony_ci } 36511cb0ef41Sopenharmony_ci break; 36521cb0ef41Sopenharmony_ci case Ugreater_equal: 36531cb0ef41Sopenharmony_ci // rs >= rt 36541cb0ef41Sopenharmony_ci if (rt.is_reg() && rs.code() == rt.rm().code()) { 36551cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset26)) return false; 36561cb0ef41Sopenharmony_ci bc(offset); 36571cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 36581cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset21, &scratch, rt)) 36591cb0ef41Sopenharmony_ci return false; 36601cb0ef41Sopenharmony_ci beqzc(scratch, offset); 36611cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 36621cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset26)) return false; 36631cb0ef41Sopenharmony_ci bc(offset); 36641cb0ef41Sopenharmony_ci } else { 36651cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 36661cb0ef41Sopenharmony_ci return false; 36671cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 36681cb0ef41Sopenharmony_ci bgeuc(rs, scratch, offset); 36691cb0ef41Sopenharmony_ci } 36701cb0ef41Sopenharmony_ci break; 36711cb0ef41Sopenharmony_ci case Uless: 36721cb0ef41Sopenharmony_ci // rs < rt 36731cb0ef41Sopenharmony_ci if (rt.is_reg() && rs.code() == rt.rm().code()) { 36741cb0ef41Sopenharmony_ci break; // No code needs to be emitted. 36751cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 36761cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset21, &scratch, rt)) 36771cb0ef41Sopenharmony_ci return false; 36781cb0ef41Sopenharmony_ci bnezc(scratch, offset); 36791cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 36801cb0ef41Sopenharmony_ci break; // No code needs to be emitted. 36811cb0ef41Sopenharmony_ci } else { 36821cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 36831cb0ef41Sopenharmony_ci return false; 36841cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 36851cb0ef41Sopenharmony_ci bltuc(rs, scratch, offset); 36861cb0ef41Sopenharmony_ci } 36871cb0ef41Sopenharmony_ci break; 36881cb0ef41Sopenharmony_ci case Uless_equal: 36891cb0ef41Sopenharmony_ci // rs <= rt 36901cb0ef41Sopenharmony_ci if (rt.is_reg() && rs.code() == rt.rm().code()) { 36911cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset26)) return false; 36921cb0ef41Sopenharmony_ci bc(offset); 36931cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 36941cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset26, &scratch, rt)) 36951cb0ef41Sopenharmony_ci return false; 36961cb0ef41Sopenharmony_ci bc(offset); 36971cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 36981cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset21)) return false; 36991cb0ef41Sopenharmony_ci beqzc(rs, offset); 37001cb0ef41Sopenharmony_ci } else { 37011cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 37021cb0ef41Sopenharmony_ci return false; 37031cb0ef41Sopenharmony_ci DCHECK(rs != scratch); 37041cb0ef41Sopenharmony_ci bgeuc(scratch, rs, offset); 37051cb0ef41Sopenharmony_ci } 37061cb0ef41Sopenharmony_ci break; 37071cb0ef41Sopenharmony_ci default: 37081cb0ef41Sopenharmony_ci UNREACHABLE(); 37091cb0ef41Sopenharmony_ci } 37101cb0ef41Sopenharmony_ci } 37111cb0ef41Sopenharmony_ci CheckTrampolinePoolQuick(1); 37121cb0ef41Sopenharmony_ci return true; 37131cb0ef41Sopenharmony_ci} 37141cb0ef41Sopenharmony_ci 37151cb0ef41Sopenharmony_cibool TurboAssembler::BranchShortHelper(int16_t offset, Label* L, Condition cond, 37161cb0ef41Sopenharmony_ci Register rs, const Operand& rt, 37171cb0ef41Sopenharmony_ci BranchDelaySlot bdslot) { 37181cb0ef41Sopenharmony_ci DCHECK(L == nullptr || offset == 0); 37191cb0ef41Sopenharmony_ci if (!is_near(L, OffsetSize::kOffset16)) return false; 37201cb0ef41Sopenharmony_ci 37211cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 37221cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 37231cb0ef41Sopenharmony_ci Register scratch = temps.hasAvailable() ? temps.Acquire() : t8; 37241cb0ef41Sopenharmony_ci int32_t offset32; 37251cb0ef41Sopenharmony_ci 37261cb0ef41Sopenharmony_ci // Be careful to always use shifted_branch_offset only just before the 37271cb0ef41Sopenharmony_ci // branch instruction, as the location will be remember for patching the 37281cb0ef41Sopenharmony_ci // target. 37291cb0ef41Sopenharmony_ci { 37301cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 37311cb0ef41Sopenharmony_ci switch (cond) { 37321cb0ef41Sopenharmony_ci case cc_always: 37331cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37341cb0ef41Sopenharmony_ci b(offset32); 37351cb0ef41Sopenharmony_ci break; 37361cb0ef41Sopenharmony_ci case eq: 37371cb0ef41Sopenharmony_ci if (IsZero(rt)) { 37381cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37391cb0ef41Sopenharmony_ci beq(rs, zero_reg, offset32); 37401cb0ef41Sopenharmony_ci } else { 37411cb0ef41Sopenharmony_ci // We don't want any other register but scratch clobbered. 37421cb0ef41Sopenharmony_ci scratch = GetRtAsRegisterHelper(rt, scratch); 37431cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37441cb0ef41Sopenharmony_ci beq(rs, scratch, offset32); 37451cb0ef41Sopenharmony_ci } 37461cb0ef41Sopenharmony_ci break; 37471cb0ef41Sopenharmony_ci case ne: 37481cb0ef41Sopenharmony_ci if (IsZero(rt)) { 37491cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37501cb0ef41Sopenharmony_ci bne(rs, zero_reg, offset32); 37511cb0ef41Sopenharmony_ci } else { 37521cb0ef41Sopenharmony_ci // We don't want any other register but scratch clobbered. 37531cb0ef41Sopenharmony_ci scratch = GetRtAsRegisterHelper(rt, scratch); 37541cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37551cb0ef41Sopenharmony_ci bne(rs, scratch, offset32); 37561cb0ef41Sopenharmony_ci } 37571cb0ef41Sopenharmony_ci break; 37581cb0ef41Sopenharmony_ci 37591cb0ef41Sopenharmony_ci // Signed comparison. 37601cb0ef41Sopenharmony_ci case greater: 37611cb0ef41Sopenharmony_ci if (IsZero(rt)) { 37621cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37631cb0ef41Sopenharmony_ci bgtz(rs, offset32); 37641cb0ef41Sopenharmony_ci } else { 37651cb0ef41Sopenharmony_ci Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 37661cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37671cb0ef41Sopenharmony_ci bne(scratch, zero_reg, offset32); 37681cb0ef41Sopenharmony_ci } 37691cb0ef41Sopenharmony_ci break; 37701cb0ef41Sopenharmony_ci case greater_equal: 37711cb0ef41Sopenharmony_ci if (IsZero(rt)) { 37721cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37731cb0ef41Sopenharmony_ci bgez(rs, offset32); 37741cb0ef41Sopenharmony_ci } else { 37751cb0ef41Sopenharmony_ci Slt(scratch, rs, rt); 37761cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37771cb0ef41Sopenharmony_ci beq(scratch, zero_reg, offset32); 37781cb0ef41Sopenharmony_ci } 37791cb0ef41Sopenharmony_ci break; 37801cb0ef41Sopenharmony_ci case less: 37811cb0ef41Sopenharmony_ci if (IsZero(rt)) { 37821cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37831cb0ef41Sopenharmony_ci bltz(rs, offset32); 37841cb0ef41Sopenharmony_ci } else { 37851cb0ef41Sopenharmony_ci Slt(scratch, rs, rt); 37861cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37871cb0ef41Sopenharmony_ci bne(scratch, zero_reg, offset32); 37881cb0ef41Sopenharmony_ci } 37891cb0ef41Sopenharmony_ci break; 37901cb0ef41Sopenharmony_ci case less_equal: 37911cb0ef41Sopenharmony_ci if (IsZero(rt)) { 37921cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37931cb0ef41Sopenharmony_ci blez(rs, offset32); 37941cb0ef41Sopenharmony_ci } else { 37951cb0ef41Sopenharmony_ci Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 37961cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 37971cb0ef41Sopenharmony_ci beq(scratch, zero_reg, offset32); 37981cb0ef41Sopenharmony_ci } 37991cb0ef41Sopenharmony_ci break; 38001cb0ef41Sopenharmony_ci 38011cb0ef41Sopenharmony_ci // Unsigned comparison. 38021cb0ef41Sopenharmony_ci case Ugreater: 38031cb0ef41Sopenharmony_ci if (IsZero(rt)) { 38041cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 38051cb0ef41Sopenharmony_ci bne(rs, zero_reg, offset32); 38061cb0ef41Sopenharmony_ci } else { 38071cb0ef41Sopenharmony_ci Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 38081cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 38091cb0ef41Sopenharmony_ci bne(scratch, zero_reg, offset32); 38101cb0ef41Sopenharmony_ci } 38111cb0ef41Sopenharmony_ci break; 38121cb0ef41Sopenharmony_ci case Ugreater_equal: 38131cb0ef41Sopenharmony_ci if (IsZero(rt)) { 38141cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 38151cb0ef41Sopenharmony_ci b(offset32); 38161cb0ef41Sopenharmony_ci } else { 38171cb0ef41Sopenharmony_ci Sltu(scratch, rs, rt); 38181cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 38191cb0ef41Sopenharmony_ci beq(scratch, zero_reg, offset32); 38201cb0ef41Sopenharmony_ci } 38211cb0ef41Sopenharmony_ci break; 38221cb0ef41Sopenharmony_ci case Uless: 38231cb0ef41Sopenharmony_ci if (IsZero(rt)) { 38241cb0ef41Sopenharmony_ci return true; // No code needs to be emitted. 38251cb0ef41Sopenharmony_ci } else { 38261cb0ef41Sopenharmony_ci Sltu(scratch, rs, rt); 38271cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 38281cb0ef41Sopenharmony_ci bne(scratch, zero_reg, offset32); 38291cb0ef41Sopenharmony_ci } 38301cb0ef41Sopenharmony_ci break; 38311cb0ef41Sopenharmony_ci case Uless_equal: 38321cb0ef41Sopenharmony_ci if (IsZero(rt)) { 38331cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 38341cb0ef41Sopenharmony_ci beq(rs, zero_reg, offset32); 38351cb0ef41Sopenharmony_ci } else { 38361cb0ef41Sopenharmony_ci Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 38371cb0ef41Sopenharmony_ci offset32 = GetOffset(offset, L, OffsetSize::kOffset16); 38381cb0ef41Sopenharmony_ci beq(scratch, zero_reg, offset32); 38391cb0ef41Sopenharmony_ci } 38401cb0ef41Sopenharmony_ci break; 38411cb0ef41Sopenharmony_ci default: 38421cb0ef41Sopenharmony_ci UNREACHABLE(); 38431cb0ef41Sopenharmony_ci } 38441cb0ef41Sopenharmony_ci } 38451cb0ef41Sopenharmony_ci 38461cb0ef41Sopenharmony_ci // Emit a nop in the branch delay slot if required. 38471cb0ef41Sopenharmony_ci if (bdslot == PROTECT) nop(); 38481cb0ef41Sopenharmony_ci 38491cb0ef41Sopenharmony_ci return true; 38501cb0ef41Sopenharmony_ci} 38511cb0ef41Sopenharmony_ci 38521cb0ef41Sopenharmony_cibool TurboAssembler::BranchShortCheck(int32_t offset, Label* L, Condition cond, 38531cb0ef41Sopenharmony_ci Register rs, const Operand& rt, 38541cb0ef41Sopenharmony_ci BranchDelaySlot bdslot) { 38551cb0ef41Sopenharmony_ci BRANCH_ARGS_CHECK(cond, rs, rt); 38561cb0ef41Sopenharmony_ci 38571cb0ef41Sopenharmony_ci if (!L) { 38581cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bdslot == PROTECT) { 38591cb0ef41Sopenharmony_ci DCHECK(is_int26(offset)); 38601cb0ef41Sopenharmony_ci return BranchShortHelperR6(offset, nullptr, cond, rs, rt); 38611cb0ef41Sopenharmony_ci } else { 38621cb0ef41Sopenharmony_ci DCHECK(is_int16(offset)); 38631cb0ef41Sopenharmony_ci return BranchShortHelper(offset, nullptr, cond, rs, rt, bdslot); 38641cb0ef41Sopenharmony_ci } 38651cb0ef41Sopenharmony_ci } else { 38661cb0ef41Sopenharmony_ci DCHECK_EQ(offset, 0); 38671cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bdslot == PROTECT) { 38681cb0ef41Sopenharmony_ci return BranchShortHelperR6(0, L, cond, rs, rt); 38691cb0ef41Sopenharmony_ci } else { 38701cb0ef41Sopenharmony_ci return BranchShortHelper(0, L, cond, rs, rt, bdslot); 38711cb0ef41Sopenharmony_ci } 38721cb0ef41Sopenharmony_ci } 38731cb0ef41Sopenharmony_ci} 38741cb0ef41Sopenharmony_ci 38751cb0ef41Sopenharmony_civoid TurboAssembler::BranchShort(int32_t offset, Condition cond, Register rs, 38761cb0ef41Sopenharmony_ci const Operand& rt, BranchDelaySlot bdslot) { 38771cb0ef41Sopenharmony_ci BranchShortCheck(offset, nullptr, cond, rs, rt, bdslot); 38781cb0ef41Sopenharmony_ci} 38791cb0ef41Sopenharmony_ci 38801cb0ef41Sopenharmony_civoid TurboAssembler::BranchShort(Label* L, Condition cond, Register rs, 38811cb0ef41Sopenharmony_ci const Operand& rt, BranchDelaySlot bdslot) { 38821cb0ef41Sopenharmony_ci BranchShortCheck(0, L, cond, rs, rt, bdslot); 38831cb0ef41Sopenharmony_ci} 38841cb0ef41Sopenharmony_ci 38851cb0ef41Sopenharmony_civoid TurboAssembler::BranchAndLink(int32_t offset, BranchDelaySlot bdslot) { 38861cb0ef41Sopenharmony_ci BranchAndLinkShort(offset, bdslot); 38871cb0ef41Sopenharmony_ci} 38881cb0ef41Sopenharmony_ci 38891cb0ef41Sopenharmony_civoid TurboAssembler::BranchAndLink(int32_t offset, Condition cond, Register rs, 38901cb0ef41Sopenharmony_ci const Operand& rt, BranchDelaySlot bdslot) { 38911cb0ef41Sopenharmony_ci bool is_near = BranchAndLinkShortCheck(offset, nullptr, cond, rs, rt, bdslot); 38921cb0ef41Sopenharmony_ci DCHECK(is_near); 38931cb0ef41Sopenharmony_ci USE(is_near); 38941cb0ef41Sopenharmony_ci} 38951cb0ef41Sopenharmony_ci 38961cb0ef41Sopenharmony_civoid TurboAssembler::BranchAndLink(Label* L, BranchDelaySlot bdslot) { 38971cb0ef41Sopenharmony_ci if (L->is_bound()) { 38981cb0ef41Sopenharmony_ci if (is_near_branch(L)) { 38991cb0ef41Sopenharmony_ci BranchAndLinkShort(L, bdslot); 39001cb0ef41Sopenharmony_ci } else { 39011cb0ef41Sopenharmony_ci BranchAndLinkLong(L, bdslot); 39021cb0ef41Sopenharmony_ci } 39031cb0ef41Sopenharmony_ci } else { 39041cb0ef41Sopenharmony_ci if (is_trampoline_emitted()) { 39051cb0ef41Sopenharmony_ci BranchAndLinkLong(L, bdslot); 39061cb0ef41Sopenharmony_ci } else { 39071cb0ef41Sopenharmony_ci BranchAndLinkShort(L, bdslot); 39081cb0ef41Sopenharmony_ci } 39091cb0ef41Sopenharmony_ci } 39101cb0ef41Sopenharmony_ci} 39111cb0ef41Sopenharmony_ci 39121cb0ef41Sopenharmony_civoid TurboAssembler::BranchAndLink(Label* L, Condition cond, Register rs, 39131cb0ef41Sopenharmony_ci const Operand& rt, BranchDelaySlot bdslot) { 39141cb0ef41Sopenharmony_ci if (L->is_bound()) { 39151cb0ef41Sopenharmony_ci if (!BranchAndLinkShortCheck(0, L, cond, rs, rt, bdslot)) { 39161cb0ef41Sopenharmony_ci Label skip; 39171cb0ef41Sopenharmony_ci Condition neg_cond = NegateCondition(cond); 39181cb0ef41Sopenharmony_ci BranchShort(&skip, neg_cond, rs, rt); 39191cb0ef41Sopenharmony_ci BranchAndLinkLong(L, bdslot); 39201cb0ef41Sopenharmony_ci bind(&skip); 39211cb0ef41Sopenharmony_ci } 39221cb0ef41Sopenharmony_ci } else { 39231cb0ef41Sopenharmony_ci if (is_trampoline_emitted()) { 39241cb0ef41Sopenharmony_ci Label skip; 39251cb0ef41Sopenharmony_ci Condition neg_cond = NegateCondition(cond); 39261cb0ef41Sopenharmony_ci BranchShort(&skip, neg_cond, rs, rt); 39271cb0ef41Sopenharmony_ci BranchAndLinkLong(L, bdslot); 39281cb0ef41Sopenharmony_ci bind(&skip); 39291cb0ef41Sopenharmony_ci } else { 39301cb0ef41Sopenharmony_ci BranchAndLinkShortCheck(0, L, cond, rs, rt, bdslot); 39311cb0ef41Sopenharmony_ci } 39321cb0ef41Sopenharmony_ci } 39331cb0ef41Sopenharmony_ci} 39341cb0ef41Sopenharmony_ci 39351cb0ef41Sopenharmony_civoid TurboAssembler::BranchAndLinkShortHelper(int16_t offset, Label* L, 39361cb0ef41Sopenharmony_ci BranchDelaySlot bdslot) { 39371cb0ef41Sopenharmony_ci DCHECK(L == nullptr || offset == 0); 39381cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 39391cb0ef41Sopenharmony_ci bal(offset); 39401cb0ef41Sopenharmony_ci 39411cb0ef41Sopenharmony_ci // Emit a nop in the branch delay slot if required. 39421cb0ef41Sopenharmony_ci if (bdslot == PROTECT) nop(); 39431cb0ef41Sopenharmony_ci} 39441cb0ef41Sopenharmony_ci 39451cb0ef41Sopenharmony_civoid TurboAssembler::BranchAndLinkShortHelperR6(int32_t offset, Label* L) { 39461cb0ef41Sopenharmony_ci DCHECK(L == nullptr || offset == 0); 39471cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset26); 39481cb0ef41Sopenharmony_ci balc(offset); 39491cb0ef41Sopenharmony_ci} 39501cb0ef41Sopenharmony_ci 39511cb0ef41Sopenharmony_civoid TurboAssembler::BranchAndLinkShort(int32_t offset, 39521cb0ef41Sopenharmony_ci BranchDelaySlot bdslot) { 39531cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bdslot == PROTECT) { 39541cb0ef41Sopenharmony_ci DCHECK(is_int26(offset)); 39551cb0ef41Sopenharmony_ci BranchAndLinkShortHelperR6(offset, nullptr); 39561cb0ef41Sopenharmony_ci } else { 39571cb0ef41Sopenharmony_ci DCHECK(is_int16(offset)); 39581cb0ef41Sopenharmony_ci BranchAndLinkShortHelper(offset, nullptr, bdslot); 39591cb0ef41Sopenharmony_ci } 39601cb0ef41Sopenharmony_ci} 39611cb0ef41Sopenharmony_ci 39621cb0ef41Sopenharmony_civoid TurboAssembler::BranchAndLinkShort(Label* L, BranchDelaySlot bdslot) { 39631cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bdslot == PROTECT) { 39641cb0ef41Sopenharmony_ci BranchAndLinkShortHelperR6(0, L); 39651cb0ef41Sopenharmony_ci } else { 39661cb0ef41Sopenharmony_ci BranchAndLinkShortHelper(0, L, bdslot); 39671cb0ef41Sopenharmony_ci } 39681cb0ef41Sopenharmony_ci} 39691cb0ef41Sopenharmony_ci 39701cb0ef41Sopenharmony_cibool TurboAssembler::BranchAndLinkShortHelperR6(int32_t offset, Label* L, 39711cb0ef41Sopenharmony_ci Condition cond, Register rs, 39721cb0ef41Sopenharmony_ci const Operand& rt) { 39731cb0ef41Sopenharmony_ci DCHECK(L == nullptr || offset == 0); 39741cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 39751cb0ef41Sopenharmony_ci Register scratch = temps.hasAvailable() ? temps.Acquire() : t8; 39761cb0ef41Sopenharmony_ci OffsetSize bits = OffsetSize::kOffset16; 39771cb0ef41Sopenharmony_ci 39781cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 39791cb0ef41Sopenharmony_ci DCHECK((cond == cc_always && is_int26(offset)) || is_int16(offset)); 39801cb0ef41Sopenharmony_ci switch (cond) { 39811cb0ef41Sopenharmony_ci case cc_always: 39821cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset26)) return false; 39831cb0ef41Sopenharmony_ci balc(offset); 39841cb0ef41Sopenharmony_ci break; 39851cb0ef41Sopenharmony_ci case eq: 39861cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 39871cb0ef41Sopenharmony_ci Subu(scratch, rs, rt); 39881cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, bits); 39891cb0ef41Sopenharmony_ci beqzalc(scratch, offset); 39901cb0ef41Sopenharmony_ci break; 39911cb0ef41Sopenharmony_ci case ne: 39921cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 39931cb0ef41Sopenharmony_ci Subu(scratch, rs, rt); 39941cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, bits); 39951cb0ef41Sopenharmony_ci bnezalc(scratch, offset); 39961cb0ef41Sopenharmony_ci break; 39971cb0ef41Sopenharmony_ci 39981cb0ef41Sopenharmony_ci // Signed comparison. 39991cb0ef41Sopenharmony_ci case greater: 40001cb0ef41Sopenharmony_ci // rs > rt 40011cb0ef41Sopenharmony_ci if (rs.code() == rt.rm().code()) { 40021cb0ef41Sopenharmony_ci break; // No code needs to be emitted. 40031cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 40041cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 40051cb0ef41Sopenharmony_ci return false; 40061cb0ef41Sopenharmony_ci bltzalc(scratch, offset); 40071cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 40081cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16)) return false; 40091cb0ef41Sopenharmony_ci bgtzalc(rs, offset); 40101cb0ef41Sopenharmony_ci } else { 40111cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 40121cb0ef41Sopenharmony_ci Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 40131cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, bits); 40141cb0ef41Sopenharmony_ci bnezalc(scratch, offset); 40151cb0ef41Sopenharmony_ci } 40161cb0ef41Sopenharmony_ci break; 40171cb0ef41Sopenharmony_ci case greater_equal: 40181cb0ef41Sopenharmony_ci // rs >= rt 40191cb0ef41Sopenharmony_ci if (rs.code() == rt.rm().code()) { 40201cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset26)) return false; 40211cb0ef41Sopenharmony_ci balc(offset); 40221cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 40231cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 40241cb0ef41Sopenharmony_ci return false; 40251cb0ef41Sopenharmony_ci blezalc(scratch, offset); 40261cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 40271cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16)) return false; 40281cb0ef41Sopenharmony_ci bgezalc(rs, offset); 40291cb0ef41Sopenharmony_ci } else { 40301cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 40311cb0ef41Sopenharmony_ci Slt(scratch, rs, rt); 40321cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, bits); 40331cb0ef41Sopenharmony_ci beqzalc(scratch, offset); 40341cb0ef41Sopenharmony_ci } 40351cb0ef41Sopenharmony_ci break; 40361cb0ef41Sopenharmony_ci case less: 40371cb0ef41Sopenharmony_ci // rs < rt 40381cb0ef41Sopenharmony_ci if (rs.code() == rt.rm().code()) { 40391cb0ef41Sopenharmony_ci break; // No code needs to be emitted. 40401cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 40411cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 40421cb0ef41Sopenharmony_ci return false; 40431cb0ef41Sopenharmony_ci bgtzalc(scratch, offset); 40441cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 40451cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16)) return false; 40461cb0ef41Sopenharmony_ci bltzalc(rs, offset); 40471cb0ef41Sopenharmony_ci } else { 40481cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 40491cb0ef41Sopenharmony_ci Slt(scratch, rs, rt); 40501cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, bits); 40511cb0ef41Sopenharmony_ci bnezalc(scratch, offset); 40521cb0ef41Sopenharmony_ci } 40531cb0ef41Sopenharmony_ci break; 40541cb0ef41Sopenharmony_ci case less_equal: 40551cb0ef41Sopenharmony_ci // rs <= r2 40561cb0ef41Sopenharmony_ci if (rs.code() == rt.rm().code()) { 40571cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset26)) return false; 40581cb0ef41Sopenharmony_ci balc(offset); 40591cb0ef41Sopenharmony_ci } else if (rs == zero_reg) { 40601cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16, &scratch, rt)) 40611cb0ef41Sopenharmony_ci return false; 40621cb0ef41Sopenharmony_ci bgezalc(scratch, offset); 40631cb0ef41Sopenharmony_ci } else if (IsZero(rt)) { 40641cb0ef41Sopenharmony_ci if (!CalculateOffset(L, &offset, OffsetSize::kOffset16)) return false; 40651cb0ef41Sopenharmony_ci blezalc(rs, offset); 40661cb0ef41Sopenharmony_ci } else { 40671cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 40681cb0ef41Sopenharmony_ci Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 40691cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, bits); 40701cb0ef41Sopenharmony_ci beqzalc(scratch, offset); 40711cb0ef41Sopenharmony_ci } 40721cb0ef41Sopenharmony_ci break; 40731cb0ef41Sopenharmony_ci 40741cb0ef41Sopenharmony_ci // Unsigned comparison. 40751cb0ef41Sopenharmony_ci case Ugreater: 40761cb0ef41Sopenharmony_ci // rs > r2 40771cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 40781cb0ef41Sopenharmony_ci Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 40791cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, bits); 40801cb0ef41Sopenharmony_ci bnezalc(scratch, offset); 40811cb0ef41Sopenharmony_ci break; 40821cb0ef41Sopenharmony_ci case Ugreater_equal: 40831cb0ef41Sopenharmony_ci // rs >= r2 40841cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 40851cb0ef41Sopenharmony_ci Sltu(scratch, rs, rt); 40861cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, bits); 40871cb0ef41Sopenharmony_ci beqzalc(scratch, offset); 40881cb0ef41Sopenharmony_ci break; 40891cb0ef41Sopenharmony_ci case Uless: 40901cb0ef41Sopenharmony_ci // rs < r2 40911cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 40921cb0ef41Sopenharmony_ci Sltu(scratch, rs, rt); 40931cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, bits); 40941cb0ef41Sopenharmony_ci bnezalc(scratch, offset); 40951cb0ef41Sopenharmony_ci break; 40961cb0ef41Sopenharmony_ci case Uless_equal: 40971cb0ef41Sopenharmony_ci // rs <= r2 40981cb0ef41Sopenharmony_ci if (!is_near(L, bits)) return false; 40991cb0ef41Sopenharmony_ci Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 41001cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, bits); 41011cb0ef41Sopenharmony_ci beqzalc(scratch, offset); 41021cb0ef41Sopenharmony_ci break; 41031cb0ef41Sopenharmony_ci default: 41041cb0ef41Sopenharmony_ci UNREACHABLE(); 41051cb0ef41Sopenharmony_ci } 41061cb0ef41Sopenharmony_ci return true; 41071cb0ef41Sopenharmony_ci} 41081cb0ef41Sopenharmony_ci 41091cb0ef41Sopenharmony_ci// Pre r6 we need to use a bgezal or bltzal, but they can't be used directly 41101cb0ef41Sopenharmony_ci// with the slt instructions. We could use sub or add instead but we would miss 41111cb0ef41Sopenharmony_ci// overflow cases, so we keep slt and add an intermediate third instruction. 41121cb0ef41Sopenharmony_cibool TurboAssembler::BranchAndLinkShortHelper(int16_t offset, Label* L, 41131cb0ef41Sopenharmony_ci Condition cond, Register rs, 41141cb0ef41Sopenharmony_ci const Operand& rt, 41151cb0ef41Sopenharmony_ci BranchDelaySlot bdslot) { 41161cb0ef41Sopenharmony_ci DCHECK(L == nullptr || offset == 0); 41171cb0ef41Sopenharmony_ci if (!is_near(L, OffsetSize::kOffset16)) return false; 41181cb0ef41Sopenharmony_ci 41191cb0ef41Sopenharmony_ci Register scratch = t8; 41201cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 41211cb0ef41Sopenharmony_ci 41221cb0ef41Sopenharmony_ci switch (cond) { 41231cb0ef41Sopenharmony_ci case cc_always: 41241cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 41251cb0ef41Sopenharmony_ci bal(offset); 41261cb0ef41Sopenharmony_ci break; 41271cb0ef41Sopenharmony_ci case eq: 41281cb0ef41Sopenharmony_ci bne(rs, GetRtAsRegisterHelper(rt, scratch), 2); 41291cb0ef41Sopenharmony_ci nop(); 41301cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 41311cb0ef41Sopenharmony_ci bal(offset); 41321cb0ef41Sopenharmony_ci break; 41331cb0ef41Sopenharmony_ci case ne: 41341cb0ef41Sopenharmony_ci beq(rs, GetRtAsRegisterHelper(rt, scratch), 2); 41351cb0ef41Sopenharmony_ci nop(); 41361cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 41371cb0ef41Sopenharmony_ci bal(offset); 41381cb0ef41Sopenharmony_ci break; 41391cb0ef41Sopenharmony_ci 41401cb0ef41Sopenharmony_ci // Signed comparison. 41411cb0ef41Sopenharmony_ci case greater: 41421cb0ef41Sopenharmony_ci Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 41431cb0ef41Sopenharmony_ci addiu(scratch, scratch, -1); 41441cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 41451cb0ef41Sopenharmony_ci bgezal(scratch, offset); 41461cb0ef41Sopenharmony_ci break; 41471cb0ef41Sopenharmony_ci case greater_equal: 41481cb0ef41Sopenharmony_ci Slt(scratch, rs, rt); 41491cb0ef41Sopenharmony_ci addiu(scratch, scratch, -1); 41501cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 41511cb0ef41Sopenharmony_ci bltzal(scratch, offset); 41521cb0ef41Sopenharmony_ci break; 41531cb0ef41Sopenharmony_ci case less: 41541cb0ef41Sopenharmony_ci Slt(scratch, rs, rt); 41551cb0ef41Sopenharmony_ci addiu(scratch, scratch, -1); 41561cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 41571cb0ef41Sopenharmony_ci bgezal(scratch, offset); 41581cb0ef41Sopenharmony_ci break; 41591cb0ef41Sopenharmony_ci case less_equal: 41601cb0ef41Sopenharmony_ci Slt(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 41611cb0ef41Sopenharmony_ci addiu(scratch, scratch, -1); 41621cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 41631cb0ef41Sopenharmony_ci bltzal(scratch, offset); 41641cb0ef41Sopenharmony_ci break; 41651cb0ef41Sopenharmony_ci 41661cb0ef41Sopenharmony_ci // Unsigned comparison. 41671cb0ef41Sopenharmony_ci case Ugreater: 41681cb0ef41Sopenharmony_ci Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 41691cb0ef41Sopenharmony_ci addiu(scratch, scratch, -1); 41701cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 41711cb0ef41Sopenharmony_ci bgezal(scratch, offset); 41721cb0ef41Sopenharmony_ci break; 41731cb0ef41Sopenharmony_ci case Ugreater_equal: 41741cb0ef41Sopenharmony_ci Sltu(scratch, rs, rt); 41751cb0ef41Sopenharmony_ci addiu(scratch, scratch, -1); 41761cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 41771cb0ef41Sopenharmony_ci bltzal(scratch, offset); 41781cb0ef41Sopenharmony_ci break; 41791cb0ef41Sopenharmony_ci case Uless: 41801cb0ef41Sopenharmony_ci Sltu(scratch, rs, rt); 41811cb0ef41Sopenharmony_ci addiu(scratch, scratch, -1); 41821cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 41831cb0ef41Sopenharmony_ci bgezal(scratch, offset); 41841cb0ef41Sopenharmony_ci break; 41851cb0ef41Sopenharmony_ci case Uless_equal: 41861cb0ef41Sopenharmony_ci Sltu(scratch, GetRtAsRegisterHelper(rt, scratch), rs); 41871cb0ef41Sopenharmony_ci addiu(scratch, scratch, -1); 41881cb0ef41Sopenharmony_ci offset = GetOffset(offset, L, OffsetSize::kOffset16); 41891cb0ef41Sopenharmony_ci bltzal(scratch, offset); 41901cb0ef41Sopenharmony_ci break; 41911cb0ef41Sopenharmony_ci 41921cb0ef41Sopenharmony_ci default: 41931cb0ef41Sopenharmony_ci UNREACHABLE(); 41941cb0ef41Sopenharmony_ci } 41951cb0ef41Sopenharmony_ci 41961cb0ef41Sopenharmony_ci // Emit a nop in the branch delay slot if required. 41971cb0ef41Sopenharmony_ci if (bdslot == PROTECT) nop(); 41981cb0ef41Sopenharmony_ci 41991cb0ef41Sopenharmony_ci return true; 42001cb0ef41Sopenharmony_ci} 42011cb0ef41Sopenharmony_ci 42021cb0ef41Sopenharmony_cibool TurboAssembler::BranchAndLinkShortCheck(int32_t offset, Label* L, 42031cb0ef41Sopenharmony_ci Condition cond, Register rs, 42041cb0ef41Sopenharmony_ci const Operand& rt, 42051cb0ef41Sopenharmony_ci BranchDelaySlot bdslot) { 42061cb0ef41Sopenharmony_ci BRANCH_ARGS_CHECK(cond, rs, rt); 42071cb0ef41Sopenharmony_ci 42081cb0ef41Sopenharmony_ci if (!L) { 42091cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bdslot == PROTECT) { 42101cb0ef41Sopenharmony_ci DCHECK(is_int26(offset)); 42111cb0ef41Sopenharmony_ci return BranchAndLinkShortHelperR6(offset, nullptr, cond, rs, rt); 42121cb0ef41Sopenharmony_ci } else { 42131cb0ef41Sopenharmony_ci DCHECK(is_int16(offset)); 42141cb0ef41Sopenharmony_ci return BranchAndLinkShortHelper(offset, nullptr, cond, rs, rt, bdslot); 42151cb0ef41Sopenharmony_ci } 42161cb0ef41Sopenharmony_ci } else { 42171cb0ef41Sopenharmony_ci DCHECK_EQ(offset, 0); 42181cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bdslot == PROTECT) { 42191cb0ef41Sopenharmony_ci return BranchAndLinkShortHelperR6(0, L, cond, rs, rt); 42201cb0ef41Sopenharmony_ci } else { 42211cb0ef41Sopenharmony_ci return BranchAndLinkShortHelper(0, L, cond, rs, rt, bdslot); 42221cb0ef41Sopenharmony_ci } 42231cb0ef41Sopenharmony_ci } 42241cb0ef41Sopenharmony_ci} 42251cb0ef41Sopenharmony_ci 42261cb0ef41Sopenharmony_civoid TurboAssembler::LoadFromConstantsTable(Register destination, 42271cb0ef41Sopenharmony_ci int constant_index) { 42281cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 42291cb0ef41Sopenharmony_ci DCHECK(RootsTable::IsImmortalImmovable(RootIndex::kBuiltinsConstantsTable)); 42301cb0ef41Sopenharmony_ci LoadRoot(destination, RootIndex::kBuiltinsConstantsTable); 42311cb0ef41Sopenharmony_ci Ld(destination, 42321cb0ef41Sopenharmony_ci FieldMemOperand(destination, 42331cb0ef41Sopenharmony_ci FixedArray::kHeaderSize + constant_index * kPointerSize)); 42341cb0ef41Sopenharmony_ci} 42351cb0ef41Sopenharmony_ci 42361cb0ef41Sopenharmony_civoid TurboAssembler::LoadRootRelative(Register destination, int32_t offset) { 42371cb0ef41Sopenharmony_ci Ld(destination, MemOperand(kRootRegister, offset)); 42381cb0ef41Sopenharmony_ci} 42391cb0ef41Sopenharmony_ci 42401cb0ef41Sopenharmony_civoid TurboAssembler::LoadRootRegisterOffset(Register destination, 42411cb0ef41Sopenharmony_ci intptr_t offset) { 42421cb0ef41Sopenharmony_ci if (offset == 0) { 42431cb0ef41Sopenharmony_ci Move(destination, kRootRegister); 42441cb0ef41Sopenharmony_ci } else { 42451cb0ef41Sopenharmony_ci Daddu(destination, kRootRegister, Operand(offset)); 42461cb0ef41Sopenharmony_ci } 42471cb0ef41Sopenharmony_ci} 42481cb0ef41Sopenharmony_ci 42491cb0ef41Sopenharmony_civoid TurboAssembler::Jump(Register target, Condition cond, Register rs, 42501cb0ef41Sopenharmony_ci const Operand& rt, BranchDelaySlot bd) { 42511cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 42521cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bd == PROTECT) { 42531cb0ef41Sopenharmony_ci if (cond == cc_always) { 42541cb0ef41Sopenharmony_ci jic(target, 0); 42551cb0ef41Sopenharmony_ci } else { 42561cb0ef41Sopenharmony_ci BRANCH_ARGS_CHECK(cond, rs, rt); 42571cb0ef41Sopenharmony_ci Branch(2, NegateCondition(cond), rs, rt); 42581cb0ef41Sopenharmony_ci jic(target, 0); 42591cb0ef41Sopenharmony_ci } 42601cb0ef41Sopenharmony_ci } else { 42611cb0ef41Sopenharmony_ci if (cond == cc_always) { 42621cb0ef41Sopenharmony_ci jr(target); 42631cb0ef41Sopenharmony_ci } else { 42641cb0ef41Sopenharmony_ci BRANCH_ARGS_CHECK(cond, rs, rt); 42651cb0ef41Sopenharmony_ci Branch(2, NegateCondition(cond), rs, rt); 42661cb0ef41Sopenharmony_ci jr(target); 42671cb0ef41Sopenharmony_ci } 42681cb0ef41Sopenharmony_ci // Emit a nop in the branch delay slot if required. 42691cb0ef41Sopenharmony_ci if (bd == PROTECT) nop(); 42701cb0ef41Sopenharmony_ci } 42711cb0ef41Sopenharmony_ci} 42721cb0ef41Sopenharmony_ci 42731cb0ef41Sopenharmony_civoid TurboAssembler::Jump(intptr_t target, RelocInfo::Mode rmode, 42741cb0ef41Sopenharmony_ci Condition cond, Register rs, const Operand& rt, 42751cb0ef41Sopenharmony_ci BranchDelaySlot bd) { 42761cb0ef41Sopenharmony_ci Label skip; 42771cb0ef41Sopenharmony_ci if (cond != cc_always) { 42781cb0ef41Sopenharmony_ci Branch(USE_DELAY_SLOT, &skip, NegateCondition(cond), rs, rt); 42791cb0ef41Sopenharmony_ci } 42801cb0ef41Sopenharmony_ci // The first instruction of 'li' may be placed in the delay slot. 42811cb0ef41Sopenharmony_ci // This is not an issue, t9 is expected to be clobbered anyway. 42821cb0ef41Sopenharmony_ci { 42831cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 42841cb0ef41Sopenharmony_ci li(t9, Operand(target, rmode)); 42851cb0ef41Sopenharmony_ci Jump(t9, al, zero_reg, Operand(zero_reg), bd); 42861cb0ef41Sopenharmony_ci bind(&skip); 42871cb0ef41Sopenharmony_ci } 42881cb0ef41Sopenharmony_ci} 42891cb0ef41Sopenharmony_ci 42901cb0ef41Sopenharmony_civoid TurboAssembler::Jump(Address target, RelocInfo::Mode rmode, Condition cond, 42911cb0ef41Sopenharmony_ci Register rs, const Operand& rt, BranchDelaySlot bd) { 42921cb0ef41Sopenharmony_ci DCHECK(!RelocInfo::IsCodeTarget(rmode)); 42931cb0ef41Sopenharmony_ci Jump(static_cast<intptr_t>(target), rmode, cond, rs, rt, bd); 42941cb0ef41Sopenharmony_ci} 42951cb0ef41Sopenharmony_ci 42961cb0ef41Sopenharmony_civoid TurboAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode, 42971cb0ef41Sopenharmony_ci Condition cond, Register rs, const Operand& rt, 42981cb0ef41Sopenharmony_ci BranchDelaySlot bd) { 42991cb0ef41Sopenharmony_ci DCHECK(RelocInfo::IsCodeTarget(rmode)); 43001cb0ef41Sopenharmony_ci 43011cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 43021cb0ef41Sopenharmony_ci if (root_array_available_ && options().isolate_independent_code) { 43031cb0ef41Sopenharmony_ci IndirectLoadConstant(t9, code); 43041cb0ef41Sopenharmony_ci Daddu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); 43051cb0ef41Sopenharmony_ci Jump(t9, cond, rs, rt, bd); 43061cb0ef41Sopenharmony_ci return; 43071cb0ef41Sopenharmony_ci } else if (options().inline_offheap_trampolines) { 43081cb0ef41Sopenharmony_ci Builtin builtin = Builtin::kNoBuiltinId; 43091cb0ef41Sopenharmony_ci if (isolate()->builtins()->IsBuiltinHandle(code, &builtin) && 43101cb0ef41Sopenharmony_ci Builtins::IsIsolateIndependent(builtin)) { 43111cb0ef41Sopenharmony_ci // Inline the trampoline. 43121cb0ef41Sopenharmony_ci RecordCommentForOffHeapTrampoline(builtin); 43131cb0ef41Sopenharmony_ci li(t9, Operand(BuiltinEntry(builtin), RelocInfo::OFF_HEAP_TARGET)); 43141cb0ef41Sopenharmony_ci Jump(t9, cond, rs, rt, bd); 43151cb0ef41Sopenharmony_ci RecordComment("]"); 43161cb0ef41Sopenharmony_ci return; 43171cb0ef41Sopenharmony_ci } 43181cb0ef41Sopenharmony_ci } 43191cb0ef41Sopenharmony_ci 43201cb0ef41Sopenharmony_ci Jump(static_cast<intptr_t>(code.address()), rmode, cond, rs, rt, bd); 43211cb0ef41Sopenharmony_ci} 43221cb0ef41Sopenharmony_ci 43231cb0ef41Sopenharmony_civoid TurboAssembler::Jump(const ExternalReference& reference) { 43241cb0ef41Sopenharmony_ci li(t9, reference); 43251cb0ef41Sopenharmony_ci Jump(t9); 43261cb0ef41Sopenharmony_ci} 43271cb0ef41Sopenharmony_ci 43281cb0ef41Sopenharmony_ci// Note: To call gcc-compiled C code on mips, you must call through t9. 43291cb0ef41Sopenharmony_civoid TurboAssembler::Call(Register target, Condition cond, Register rs, 43301cb0ef41Sopenharmony_ci const Operand& rt, BranchDelaySlot bd) { 43311cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 43321cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bd == PROTECT) { 43331cb0ef41Sopenharmony_ci if (cond == cc_always) { 43341cb0ef41Sopenharmony_ci jialc(target, 0); 43351cb0ef41Sopenharmony_ci } else { 43361cb0ef41Sopenharmony_ci BRANCH_ARGS_CHECK(cond, rs, rt); 43371cb0ef41Sopenharmony_ci Branch(2, NegateCondition(cond), rs, rt); 43381cb0ef41Sopenharmony_ci jialc(target, 0); 43391cb0ef41Sopenharmony_ci } 43401cb0ef41Sopenharmony_ci } else { 43411cb0ef41Sopenharmony_ci if (cond == cc_always) { 43421cb0ef41Sopenharmony_ci jalr(target); 43431cb0ef41Sopenharmony_ci } else { 43441cb0ef41Sopenharmony_ci BRANCH_ARGS_CHECK(cond, rs, rt); 43451cb0ef41Sopenharmony_ci Branch(2, NegateCondition(cond), rs, rt); 43461cb0ef41Sopenharmony_ci jalr(target); 43471cb0ef41Sopenharmony_ci } 43481cb0ef41Sopenharmony_ci // Emit a nop in the branch delay slot if required. 43491cb0ef41Sopenharmony_ci if (bd == PROTECT) nop(); 43501cb0ef41Sopenharmony_ci } 43511cb0ef41Sopenharmony_ci set_pc_for_safepoint(); 43521cb0ef41Sopenharmony_ci} 43531cb0ef41Sopenharmony_ci 43541cb0ef41Sopenharmony_civoid MacroAssembler::JumpIfIsInRange(Register value, unsigned lower_limit, 43551cb0ef41Sopenharmony_ci unsigned higher_limit, 43561cb0ef41Sopenharmony_ci Label* on_in_range) { 43571cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 43581cb0ef41Sopenharmony_ci if (lower_limit != 0) { 43591cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 43601cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 43611cb0ef41Sopenharmony_ci Dsubu(scratch, value, Operand(lower_limit)); 43621cb0ef41Sopenharmony_ci Branch(on_in_range, ls, scratch, Operand(higher_limit - lower_limit)); 43631cb0ef41Sopenharmony_ci } else { 43641cb0ef41Sopenharmony_ci Branch(on_in_range, ls, value, Operand(higher_limit - lower_limit)); 43651cb0ef41Sopenharmony_ci } 43661cb0ef41Sopenharmony_ci} 43671cb0ef41Sopenharmony_ci 43681cb0ef41Sopenharmony_civoid TurboAssembler::Call(Address target, RelocInfo::Mode rmode, Condition cond, 43691cb0ef41Sopenharmony_ci Register rs, const Operand& rt, BranchDelaySlot bd) { 43701cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 43711cb0ef41Sopenharmony_ci li(t9, Operand(static_cast<int64_t>(target), rmode), ADDRESS_LOAD); 43721cb0ef41Sopenharmony_ci Call(t9, cond, rs, rt, bd); 43731cb0ef41Sopenharmony_ci} 43741cb0ef41Sopenharmony_ci 43751cb0ef41Sopenharmony_civoid TurboAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode, 43761cb0ef41Sopenharmony_ci Condition cond, Register rs, const Operand& rt, 43771cb0ef41Sopenharmony_ci BranchDelaySlot bd) { 43781cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 43791cb0ef41Sopenharmony_ci 43801cb0ef41Sopenharmony_ci if (root_array_available_ && options().isolate_independent_code) { 43811cb0ef41Sopenharmony_ci IndirectLoadConstant(t9, code); 43821cb0ef41Sopenharmony_ci Daddu(t9, t9, Operand(Code::kHeaderSize - kHeapObjectTag)); 43831cb0ef41Sopenharmony_ci Call(t9, cond, rs, rt, bd); 43841cb0ef41Sopenharmony_ci return; 43851cb0ef41Sopenharmony_ci } else if (options().inline_offheap_trampolines) { 43861cb0ef41Sopenharmony_ci Builtin builtin = Builtin::kNoBuiltinId; 43871cb0ef41Sopenharmony_ci if (isolate()->builtins()->IsBuiltinHandle(code, &builtin) && 43881cb0ef41Sopenharmony_ci Builtins::IsIsolateIndependent(builtin)) { 43891cb0ef41Sopenharmony_ci // Inline the trampoline. 43901cb0ef41Sopenharmony_ci RecordCommentForOffHeapTrampoline(builtin); 43911cb0ef41Sopenharmony_ci li(t9, Operand(BuiltinEntry(builtin), RelocInfo::OFF_HEAP_TARGET)); 43921cb0ef41Sopenharmony_ci Call(t9, cond, rs, rt, bd); 43931cb0ef41Sopenharmony_ci RecordComment("]"); 43941cb0ef41Sopenharmony_ci return; 43951cb0ef41Sopenharmony_ci } 43961cb0ef41Sopenharmony_ci } 43971cb0ef41Sopenharmony_ci 43981cb0ef41Sopenharmony_ci DCHECK(RelocInfo::IsCodeTarget(rmode)); 43991cb0ef41Sopenharmony_ci DCHECK(code->IsExecutable()); 44001cb0ef41Sopenharmony_ci Call(code.address(), rmode, cond, rs, rt, bd); 44011cb0ef41Sopenharmony_ci} 44021cb0ef41Sopenharmony_ci 44031cb0ef41Sopenharmony_civoid TurboAssembler::LoadEntryFromBuiltinIndex(Register builtin_index) { 44041cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 44051cb0ef41Sopenharmony_ci STATIC_ASSERT(kSystemPointerSize == 8); 44061cb0ef41Sopenharmony_ci STATIC_ASSERT(kSmiTagSize == 1); 44071cb0ef41Sopenharmony_ci STATIC_ASSERT(kSmiTag == 0); 44081cb0ef41Sopenharmony_ci 44091cb0ef41Sopenharmony_ci // The builtin_index register contains the builtin index as a Smi. 44101cb0ef41Sopenharmony_ci SmiUntag(builtin_index, builtin_index); 44111cb0ef41Sopenharmony_ci Dlsa(builtin_index, kRootRegister, builtin_index, kSystemPointerSizeLog2); 44121cb0ef41Sopenharmony_ci Ld(builtin_index, 44131cb0ef41Sopenharmony_ci MemOperand(builtin_index, IsolateData::builtin_entry_table_offset())); 44141cb0ef41Sopenharmony_ci} 44151cb0ef41Sopenharmony_civoid TurboAssembler::LoadEntryFromBuiltin(Builtin builtin, 44161cb0ef41Sopenharmony_ci Register destination) { 44171cb0ef41Sopenharmony_ci Ld(destination, EntryFromBuiltinAsOperand(builtin)); 44181cb0ef41Sopenharmony_ci} 44191cb0ef41Sopenharmony_ciMemOperand TurboAssembler::EntryFromBuiltinAsOperand(Builtin builtin) { 44201cb0ef41Sopenharmony_ci DCHECK(root_array_available()); 44211cb0ef41Sopenharmony_ci return MemOperand(kRootRegister, 44221cb0ef41Sopenharmony_ci IsolateData::BuiltinEntrySlotOffset(builtin)); 44231cb0ef41Sopenharmony_ci} 44241cb0ef41Sopenharmony_ci 44251cb0ef41Sopenharmony_civoid TurboAssembler::CallBuiltinByIndex(Register builtin_index) { 44261cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 44271cb0ef41Sopenharmony_ci LoadEntryFromBuiltinIndex(builtin_index); 44281cb0ef41Sopenharmony_ci Call(builtin_index); 44291cb0ef41Sopenharmony_ci} 44301cb0ef41Sopenharmony_civoid TurboAssembler::CallBuiltin(Builtin builtin) { 44311cb0ef41Sopenharmony_ci RecordCommentForOffHeapTrampoline(builtin); 44321cb0ef41Sopenharmony_ci Call(BuiltinEntry(builtin), RelocInfo::OFF_HEAP_TARGET); 44331cb0ef41Sopenharmony_ci RecordComment("]"); 44341cb0ef41Sopenharmony_ci} 44351cb0ef41Sopenharmony_ci 44361cb0ef41Sopenharmony_civoid TurboAssembler::PatchAndJump(Address target) { 44371cb0ef41Sopenharmony_ci if (kArchVariant != kMips64r6) { 44381cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 44391cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 44401cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 44411cb0ef41Sopenharmony_ci mov(scratch, ra); 44421cb0ef41Sopenharmony_ci bal(1); // jump to ld 44431cb0ef41Sopenharmony_ci nop(); // in the delay slot 44441cb0ef41Sopenharmony_ci ld(t9, MemOperand(ra, kInstrSize * 3)); // ra == pc_ 44451cb0ef41Sopenharmony_ci jr(t9); 44461cb0ef41Sopenharmony_ci mov(ra, scratch); // in delay slot 44471cb0ef41Sopenharmony_ci DCHECK_EQ(reinterpret_cast<uint64_t>(pc_) % 8, 0); 44481cb0ef41Sopenharmony_ci *reinterpret_cast<uint64_t*>(pc_) = target; // pc_ should be align. 44491cb0ef41Sopenharmony_ci pc_ += sizeof(uint64_t); 44501cb0ef41Sopenharmony_ci } else { 44511cb0ef41Sopenharmony_ci // TODO(mips r6): Implement. 44521cb0ef41Sopenharmony_ci UNIMPLEMENTED(); 44531cb0ef41Sopenharmony_ci } 44541cb0ef41Sopenharmony_ci} 44551cb0ef41Sopenharmony_ci 44561cb0ef41Sopenharmony_civoid TurboAssembler::StoreReturnAddressAndCall(Register target) { 44571cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 44581cb0ef41Sopenharmony_ci // This generates the final instruction sequence for calls to C functions 44591cb0ef41Sopenharmony_ci // once an exit frame has been constructed. 44601cb0ef41Sopenharmony_ci // 44611cb0ef41Sopenharmony_ci // Note that this assumes the caller code (i.e. the Code object currently 44621cb0ef41Sopenharmony_ci // being generated) is immovable or that the callee function cannot trigger 44631cb0ef41Sopenharmony_ci // GC, since the callee function will return to it. 44641cb0ef41Sopenharmony_ci 44651cb0ef41Sopenharmony_ci // Compute the return address in lr to return to after the jump below. The pc 44661cb0ef41Sopenharmony_ci // is already at '+ 8' from the current instruction; but return is after three 44671cb0ef41Sopenharmony_ci // instructions, so add another 4 to pc to get the return address. 44681cb0ef41Sopenharmony_ci 44691cb0ef41Sopenharmony_ci Assembler::BlockTrampolinePoolScope block_trampoline_pool(this); 44701cb0ef41Sopenharmony_ci static constexpr int kNumInstructionsToJump = 4; 44711cb0ef41Sopenharmony_ci Label find_ra; 44721cb0ef41Sopenharmony_ci // Adjust the value in ra to point to the correct return location, 2nd 44731cb0ef41Sopenharmony_ci // instruction past the real call into C code (the jalr(t9)), and push it. 44741cb0ef41Sopenharmony_ci // This is the return address of the exit frame. 44751cb0ef41Sopenharmony_ci if (kArchVariant >= kMips64r6) { 44761cb0ef41Sopenharmony_ci addiupc(ra, kNumInstructionsToJump + 1); 44771cb0ef41Sopenharmony_ci } else { 44781cb0ef41Sopenharmony_ci // This no-op-and-link sequence saves PC + 8 in ra register on pre-r6 MIPS 44791cb0ef41Sopenharmony_ci nal(); // nal has branch delay slot. 44801cb0ef41Sopenharmony_ci Daddu(ra, ra, kNumInstructionsToJump * kInstrSize); 44811cb0ef41Sopenharmony_ci } 44821cb0ef41Sopenharmony_ci bind(&find_ra); 44831cb0ef41Sopenharmony_ci 44841cb0ef41Sopenharmony_ci // This spot was reserved in EnterExitFrame. 44851cb0ef41Sopenharmony_ci Sd(ra, MemOperand(sp)); 44861cb0ef41Sopenharmony_ci // Stack space reservation moved to the branch delay slot below. 44871cb0ef41Sopenharmony_ci // Stack is still aligned. 44881cb0ef41Sopenharmony_ci 44891cb0ef41Sopenharmony_ci // Call the C routine. 44901cb0ef41Sopenharmony_ci mov(t9, target); // Function pointer to t9 to conform to ABI for PIC. 44911cb0ef41Sopenharmony_ci jalr(t9); 44921cb0ef41Sopenharmony_ci // Set up sp in the delay slot. 44931cb0ef41Sopenharmony_ci daddiu(sp, sp, -kCArgsSlotsSize); 44941cb0ef41Sopenharmony_ci // Make sure the stored 'ra' points to this position. 44951cb0ef41Sopenharmony_ci DCHECK_EQ(kNumInstructionsToJump, InstructionsGeneratedSince(&find_ra)); 44961cb0ef41Sopenharmony_ci} 44971cb0ef41Sopenharmony_ci 44981cb0ef41Sopenharmony_civoid TurboAssembler::Ret(Condition cond, Register rs, const Operand& rt, 44991cb0ef41Sopenharmony_ci BranchDelaySlot bd) { 45001cb0ef41Sopenharmony_ci Jump(ra, cond, rs, rt, bd); 45011cb0ef41Sopenharmony_ci} 45021cb0ef41Sopenharmony_ci 45031cb0ef41Sopenharmony_civoid TurboAssembler::BranchLong(Label* L, BranchDelaySlot bdslot) { 45041cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bdslot == PROTECT && 45051cb0ef41Sopenharmony_ci (!L->is_bound() || is_near_r6(L))) { 45061cb0ef41Sopenharmony_ci BranchShortHelperR6(0, L); 45071cb0ef41Sopenharmony_ci } else { 45081cb0ef41Sopenharmony_ci // Generate position independent long branch. 45091cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 45101cb0ef41Sopenharmony_ci int64_t imm64 = branch_long_offset(L); 45111cb0ef41Sopenharmony_ci DCHECK(is_int32(imm64)); 45121cb0ef41Sopenharmony_ci int32_t imm32 = static_cast<int32_t>(imm64); 45131cb0ef41Sopenharmony_ci or_(t8, ra, zero_reg); 45141cb0ef41Sopenharmony_ci nal(); // Read PC into ra register. 45151cb0ef41Sopenharmony_ci lui(t9, (imm32 & kHiMaskOf32) >> kLuiShift); // Branch delay slot. 45161cb0ef41Sopenharmony_ci ori(t9, t9, (imm32 & kImm16Mask)); 45171cb0ef41Sopenharmony_ci daddu(t9, ra, t9); 45181cb0ef41Sopenharmony_ci if (bdslot == USE_DELAY_SLOT) { 45191cb0ef41Sopenharmony_ci or_(ra, t8, zero_reg); 45201cb0ef41Sopenharmony_ci } 45211cb0ef41Sopenharmony_ci jr(t9); 45221cb0ef41Sopenharmony_ci // Emit a or_ in the branch delay slot if it's protected. 45231cb0ef41Sopenharmony_ci if (bdslot == PROTECT) or_(ra, t8, zero_reg); 45241cb0ef41Sopenharmony_ci } 45251cb0ef41Sopenharmony_ci} 45261cb0ef41Sopenharmony_ci 45271cb0ef41Sopenharmony_civoid TurboAssembler::BranchLong(int32_t offset, BranchDelaySlot bdslot) { 45281cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bdslot == PROTECT && (is_int26(offset))) { 45291cb0ef41Sopenharmony_ci BranchShortHelperR6(offset, nullptr); 45301cb0ef41Sopenharmony_ci } else { 45311cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 45321cb0ef41Sopenharmony_ci or_(t8, ra, zero_reg); 45331cb0ef41Sopenharmony_ci nal(); // Read PC into ra register. 45341cb0ef41Sopenharmony_ci lui(t9, (offset & kHiMaskOf32) >> kLuiShift); // Branch delay slot. 45351cb0ef41Sopenharmony_ci ori(t9, t9, (offset & kImm16Mask)); 45361cb0ef41Sopenharmony_ci daddu(t9, ra, t9); 45371cb0ef41Sopenharmony_ci if (bdslot == USE_DELAY_SLOT) { 45381cb0ef41Sopenharmony_ci or_(ra, t8, zero_reg); 45391cb0ef41Sopenharmony_ci } 45401cb0ef41Sopenharmony_ci jr(t9); 45411cb0ef41Sopenharmony_ci // Emit a or_ in the branch delay slot if it's protected. 45421cb0ef41Sopenharmony_ci if (bdslot == PROTECT) or_(ra, t8, zero_reg); 45431cb0ef41Sopenharmony_ci } 45441cb0ef41Sopenharmony_ci} 45451cb0ef41Sopenharmony_ci 45461cb0ef41Sopenharmony_civoid TurboAssembler::BranchAndLinkLong(Label* L, BranchDelaySlot bdslot) { 45471cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6 && bdslot == PROTECT && 45481cb0ef41Sopenharmony_ci (!L->is_bound() || is_near_r6(L))) { 45491cb0ef41Sopenharmony_ci BranchAndLinkShortHelperR6(0, L); 45501cb0ef41Sopenharmony_ci } else { 45511cb0ef41Sopenharmony_ci // Generate position independent long branch and link. 45521cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 45531cb0ef41Sopenharmony_ci int64_t imm64 = branch_long_offset(L); 45541cb0ef41Sopenharmony_ci DCHECK(is_int32(imm64)); 45551cb0ef41Sopenharmony_ci int32_t imm32 = static_cast<int32_t>(imm64); 45561cb0ef41Sopenharmony_ci lui(t8, (imm32 & kHiMaskOf32) >> kLuiShift); 45571cb0ef41Sopenharmony_ci nal(); // Read PC into ra register. 45581cb0ef41Sopenharmony_ci ori(t8, t8, (imm32 & kImm16Mask)); // Branch delay slot. 45591cb0ef41Sopenharmony_ci daddu(t8, ra, t8); 45601cb0ef41Sopenharmony_ci jalr(t8); 45611cb0ef41Sopenharmony_ci // Emit a nop in the branch delay slot if required. 45621cb0ef41Sopenharmony_ci if (bdslot == PROTECT) nop(); 45631cb0ef41Sopenharmony_ci } 45641cb0ef41Sopenharmony_ci} 45651cb0ef41Sopenharmony_ci 45661cb0ef41Sopenharmony_civoid TurboAssembler::DropArguments(Register count, ArgumentsCountType type, 45671cb0ef41Sopenharmony_ci ArgumentsCountMode mode, Register scratch) { 45681cb0ef41Sopenharmony_ci switch (type) { 45691cb0ef41Sopenharmony_ci case kCountIsInteger: { 45701cb0ef41Sopenharmony_ci Dlsa(sp, sp, count, kPointerSizeLog2); 45711cb0ef41Sopenharmony_ci break; 45721cb0ef41Sopenharmony_ci } 45731cb0ef41Sopenharmony_ci case kCountIsSmi: { 45741cb0ef41Sopenharmony_ci STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 45751cb0ef41Sopenharmony_ci DCHECK_NE(scratch, no_reg); 45761cb0ef41Sopenharmony_ci SmiScale(scratch, count, kPointerSizeLog2); 45771cb0ef41Sopenharmony_ci Daddu(sp, sp, scratch); 45781cb0ef41Sopenharmony_ci break; 45791cb0ef41Sopenharmony_ci } 45801cb0ef41Sopenharmony_ci case kCountIsBytes: { 45811cb0ef41Sopenharmony_ci Daddu(sp, sp, count); 45821cb0ef41Sopenharmony_ci break; 45831cb0ef41Sopenharmony_ci } 45841cb0ef41Sopenharmony_ci } 45851cb0ef41Sopenharmony_ci if (mode == kCountExcludesReceiver) { 45861cb0ef41Sopenharmony_ci Daddu(sp, sp, kSystemPointerSize); 45871cb0ef41Sopenharmony_ci } 45881cb0ef41Sopenharmony_ci} 45891cb0ef41Sopenharmony_ci 45901cb0ef41Sopenharmony_civoid TurboAssembler::DropArgumentsAndPushNewReceiver(Register argc, 45911cb0ef41Sopenharmony_ci Register receiver, 45921cb0ef41Sopenharmony_ci ArgumentsCountType type, 45931cb0ef41Sopenharmony_ci ArgumentsCountMode mode, 45941cb0ef41Sopenharmony_ci Register scratch) { 45951cb0ef41Sopenharmony_ci DCHECK(!AreAliased(argc, receiver)); 45961cb0ef41Sopenharmony_ci if (mode == kCountExcludesReceiver) { 45971cb0ef41Sopenharmony_ci // Drop arguments without receiver and override old receiver. 45981cb0ef41Sopenharmony_ci DropArguments(argc, type, kCountIncludesReceiver, scratch); 45991cb0ef41Sopenharmony_ci Sd(receiver, MemOperand(sp)); 46001cb0ef41Sopenharmony_ci } else { 46011cb0ef41Sopenharmony_ci DropArguments(argc, type, mode, scratch); 46021cb0ef41Sopenharmony_ci push(receiver); 46031cb0ef41Sopenharmony_ci } 46041cb0ef41Sopenharmony_ci} 46051cb0ef41Sopenharmony_ci 46061cb0ef41Sopenharmony_civoid TurboAssembler::DropAndRet(int drop) { 46071cb0ef41Sopenharmony_ci int32_t drop_size = drop * kSystemPointerSize; 46081cb0ef41Sopenharmony_ci DCHECK(is_int31(drop_size)); 46091cb0ef41Sopenharmony_ci 46101cb0ef41Sopenharmony_ci if (is_int16(drop_size)) { 46111cb0ef41Sopenharmony_ci Ret(USE_DELAY_SLOT); 46121cb0ef41Sopenharmony_ci daddiu(sp, sp, drop_size); 46131cb0ef41Sopenharmony_ci } else { 46141cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 46151cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 46161cb0ef41Sopenharmony_ci li(scratch, drop_size); 46171cb0ef41Sopenharmony_ci Ret(USE_DELAY_SLOT); 46181cb0ef41Sopenharmony_ci daddu(sp, sp, scratch); 46191cb0ef41Sopenharmony_ci } 46201cb0ef41Sopenharmony_ci} 46211cb0ef41Sopenharmony_ci 46221cb0ef41Sopenharmony_civoid TurboAssembler::DropAndRet(int drop, Condition cond, Register r1, 46231cb0ef41Sopenharmony_ci const Operand& r2) { 46241cb0ef41Sopenharmony_ci // Both Drop and Ret need to be conditional. 46251cb0ef41Sopenharmony_ci Label skip; 46261cb0ef41Sopenharmony_ci if (cond != cc_always) { 46271cb0ef41Sopenharmony_ci Branch(&skip, NegateCondition(cond), r1, r2); 46281cb0ef41Sopenharmony_ci } 46291cb0ef41Sopenharmony_ci 46301cb0ef41Sopenharmony_ci Drop(drop); 46311cb0ef41Sopenharmony_ci Ret(); 46321cb0ef41Sopenharmony_ci 46331cb0ef41Sopenharmony_ci if (cond != cc_always) { 46341cb0ef41Sopenharmony_ci bind(&skip); 46351cb0ef41Sopenharmony_ci } 46361cb0ef41Sopenharmony_ci} 46371cb0ef41Sopenharmony_ci 46381cb0ef41Sopenharmony_civoid TurboAssembler::Drop(int count, Condition cond, Register reg, 46391cb0ef41Sopenharmony_ci const Operand& op) { 46401cb0ef41Sopenharmony_ci if (count <= 0) { 46411cb0ef41Sopenharmony_ci return; 46421cb0ef41Sopenharmony_ci } 46431cb0ef41Sopenharmony_ci 46441cb0ef41Sopenharmony_ci Label skip; 46451cb0ef41Sopenharmony_ci 46461cb0ef41Sopenharmony_ci if (cond != al) { 46471cb0ef41Sopenharmony_ci Branch(&skip, NegateCondition(cond), reg, op); 46481cb0ef41Sopenharmony_ci } 46491cb0ef41Sopenharmony_ci 46501cb0ef41Sopenharmony_ci Daddu(sp, sp, Operand(count * kPointerSize)); 46511cb0ef41Sopenharmony_ci 46521cb0ef41Sopenharmony_ci if (cond != al) { 46531cb0ef41Sopenharmony_ci bind(&skip); 46541cb0ef41Sopenharmony_ci } 46551cb0ef41Sopenharmony_ci} 46561cb0ef41Sopenharmony_ci 46571cb0ef41Sopenharmony_civoid MacroAssembler::Swap(Register reg1, Register reg2, Register scratch) { 46581cb0ef41Sopenharmony_ci if (scratch == no_reg) { 46591cb0ef41Sopenharmony_ci Xor(reg1, reg1, Operand(reg2)); 46601cb0ef41Sopenharmony_ci Xor(reg2, reg2, Operand(reg1)); 46611cb0ef41Sopenharmony_ci Xor(reg1, reg1, Operand(reg2)); 46621cb0ef41Sopenharmony_ci } else { 46631cb0ef41Sopenharmony_ci mov(scratch, reg1); 46641cb0ef41Sopenharmony_ci mov(reg1, reg2); 46651cb0ef41Sopenharmony_ci mov(reg2, scratch); 46661cb0ef41Sopenharmony_ci } 46671cb0ef41Sopenharmony_ci} 46681cb0ef41Sopenharmony_ci 46691cb0ef41Sopenharmony_civoid TurboAssembler::Call(Label* target) { BranchAndLink(target); } 46701cb0ef41Sopenharmony_ci 46711cb0ef41Sopenharmony_civoid TurboAssembler::LoadAddress(Register dst, Label* target) { 46721cb0ef41Sopenharmony_ci uint64_t address = jump_address(target); 46731cb0ef41Sopenharmony_ci li(dst, address); 46741cb0ef41Sopenharmony_ci} 46751cb0ef41Sopenharmony_ci 46761cb0ef41Sopenharmony_civoid TurboAssembler::Push(Smi smi) { 46771cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 46781cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 46791cb0ef41Sopenharmony_ci li(scratch, Operand(smi)); 46801cb0ef41Sopenharmony_ci push(scratch); 46811cb0ef41Sopenharmony_ci} 46821cb0ef41Sopenharmony_ci 46831cb0ef41Sopenharmony_civoid TurboAssembler::Push(Handle<HeapObject> handle) { 46841cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 46851cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 46861cb0ef41Sopenharmony_ci li(scratch, Operand(handle)); 46871cb0ef41Sopenharmony_ci push(scratch); 46881cb0ef41Sopenharmony_ci} 46891cb0ef41Sopenharmony_ci 46901cb0ef41Sopenharmony_civoid TurboAssembler::PushArray(Register array, Register size, Register scratch, 46911cb0ef41Sopenharmony_ci Register scratch2, PushArrayOrder order) { 46921cb0ef41Sopenharmony_ci DCHECK(!AreAliased(array, size, scratch, scratch2)); 46931cb0ef41Sopenharmony_ci Label loop, entry; 46941cb0ef41Sopenharmony_ci if (order == PushArrayOrder::kReverse) { 46951cb0ef41Sopenharmony_ci mov(scratch, zero_reg); 46961cb0ef41Sopenharmony_ci jmp(&entry); 46971cb0ef41Sopenharmony_ci bind(&loop); 46981cb0ef41Sopenharmony_ci Dlsa(scratch2, array, scratch, kPointerSizeLog2); 46991cb0ef41Sopenharmony_ci Ld(scratch2, MemOperand(scratch2)); 47001cb0ef41Sopenharmony_ci push(scratch2); 47011cb0ef41Sopenharmony_ci Daddu(scratch, scratch, Operand(1)); 47021cb0ef41Sopenharmony_ci bind(&entry); 47031cb0ef41Sopenharmony_ci Branch(&loop, less, scratch, Operand(size)); 47041cb0ef41Sopenharmony_ci } else { 47051cb0ef41Sopenharmony_ci mov(scratch, size); 47061cb0ef41Sopenharmony_ci jmp(&entry); 47071cb0ef41Sopenharmony_ci bind(&loop); 47081cb0ef41Sopenharmony_ci Dlsa(scratch2, array, scratch, kPointerSizeLog2); 47091cb0ef41Sopenharmony_ci Ld(scratch2, MemOperand(scratch2)); 47101cb0ef41Sopenharmony_ci push(scratch2); 47111cb0ef41Sopenharmony_ci bind(&entry); 47121cb0ef41Sopenharmony_ci Daddu(scratch, scratch, Operand(-1)); 47131cb0ef41Sopenharmony_ci Branch(&loop, greater_equal, scratch, Operand(zero_reg)); 47141cb0ef41Sopenharmony_ci } 47151cb0ef41Sopenharmony_ci} 47161cb0ef41Sopenharmony_ci 47171cb0ef41Sopenharmony_ci// --------------------------------------------------------------------------- 47181cb0ef41Sopenharmony_ci// Exception handling. 47191cb0ef41Sopenharmony_ci 47201cb0ef41Sopenharmony_civoid MacroAssembler::PushStackHandler() { 47211cb0ef41Sopenharmony_ci // Adjust this code if not the case. 47221cb0ef41Sopenharmony_ci STATIC_ASSERT(StackHandlerConstants::kSize == 2 * kPointerSize); 47231cb0ef41Sopenharmony_ci STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); 47241cb0ef41Sopenharmony_ci 47251cb0ef41Sopenharmony_ci Push(Smi::zero()); // Padding. 47261cb0ef41Sopenharmony_ci 47271cb0ef41Sopenharmony_ci // Link the current handler as the next handler. 47281cb0ef41Sopenharmony_ci li(t2, 47291cb0ef41Sopenharmony_ci ExternalReference::Create(IsolateAddressId::kHandlerAddress, isolate())); 47301cb0ef41Sopenharmony_ci Ld(t1, MemOperand(t2)); 47311cb0ef41Sopenharmony_ci push(t1); 47321cb0ef41Sopenharmony_ci 47331cb0ef41Sopenharmony_ci // Set this new handler as the current one. 47341cb0ef41Sopenharmony_ci Sd(sp, MemOperand(t2)); 47351cb0ef41Sopenharmony_ci} 47361cb0ef41Sopenharmony_ci 47371cb0ef41Sopenharmony_civoid MacroAssembler::PopStackHandler() { 47381cb0ef41Sopenharmony_ci STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 47391cb0ef41Sopenharmony_ci pop(a1); 47401cb0ef41Sopenharmony_ci Daddu(sp, sp, 47411cb0ef41Sopenharmony_ci Operand( 47421cb0ef41Sopenharmony_ci static_cast<int64_t>(StackHandlerConstants::kSize - kPointerSize))); 47431cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 47441cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 47451cb0ef41Sopenharmony_ci li(scratch, 47461cb0ef41Sopenharmony_ci ExternalReference::Create(IsolateAddressId::kHandlerAddress, isolate())); 47471cb0ef41Sopenharmony_ci Sd(a1, MemOperand(scratch)); 47481cb0ef41Sopenharmony_ci} 47491cb0ef41Sopenharmony_ci 47501cb0ef41Sopenharmony_civoid TurboAssembler::FPUCanonicalizeNaN(const DoubleRegister dst, 47511cb0ef41Sopenharmony_ci const DoubleRegister src) { 47521cb0ef41Sopenharmony_ci sub_d(dst, src, kDoubleRegZero); 47531cb0ef41Sopenharmony_ci} 47541cb0ef41Sopenharmony_ci 47551cb0ef41Sopenharmony_civoid TurboAssembler::MovFromFloatResult(const DoubleRegister dst) { 47561cb0ef41Sopenharmony_ci if (IsMipsSoftFloatABI) { 47571cb0ef41Sopenharmony_ci if (kArchEndian == kLittle) { 47581cb0ef41Sopenharmony_ci Move(dst, v0, v1); 47591cb0ef41Sopenharmony_ci } else { 47601cb0ef41Sopenharmony_ci Move(dst, v1, v0); 47611cb0ef41Sopenharmony_ci } 47621cb0ef41Sopenharmony_ci } else { 47631cb0ef41Sopenharmony_ci Move(dst, f0); // Reg f0 is o32 ABI FP return value. 47641cb0ef41Sopenharmony_ci } 47651cb0ef41Sopenharmony_ci} 47661cb0ef41Sopenharmony_ci 47671cb0ef41Sopenharmony_civoid TurboAssembler::MovFromFloatParameter(const DoubleRegister dst) { 47681cb0ef41Sopenharmony_ci if (IsMipsSoftFloatABI) { 47691cb0ef41Sopenharmony_ci if (kArchEndian == kLittle) { 47701cb0ef41Sopenharmony_ci Move(dst, a0, a1); 47711cb0ef41Sopenharmony_ci } else { 47721cb0ef41Sopenharmony_ci Move(dst, a1, a0); 47731cb0ef41Sopenharmony_ci } 47741cb0ef41Sopenharmony_ci } else { 47751cb0ef41Sopenharmony_ci Move(dst, f12); // Reg f12 is n64 ABI FP first argument value. 47761cb0ef41Sopenharmony_ci } 47771cb0ef41Sopenharmony_ci} 47781cb0ef41Sopenharmony_ci 47791cb0ef41Sopenharmony_civoid TurboAssembler::MovToFloatParameter(DoubleRegister src) { 47801cb0ef41Sopenharmony_ci if (!IsMipsSoftFloatABI) { 47811cb0ef41Sopenharmony_ci Move(f12, src); 47821cb0ef41Sopenharmony_ci } else { 47831cb0ef41Sopenharmony_ci if (kArchEndian == kLittle) { 47841cb0ef41Sopenharmony_ci Move(a0, a1, src); 47851cb0ef41Sopenharmony_ci } else { 47861cb0ef41Sopenharmony_ci Move(a1, a0, src); 47871cb0ef41Sopenharmony_ci } 47881cb0ef41Sopenharmony_ci } 47891cb0ef41Sopenharmony_ci} 47901cb0ef41Sopenharmony_ci 47911cb0ef41Sopenharmony_civoid TurboAssembler::MovToFloatResult(DoubleRegister src) { 47921cb0ef41Sopenharmony_ci if (!IsMipsSoftFloatABI) { 47931cb0ef41Sopenharmony_ci Move(f0, src); 47941cb0ef41Sopenharmony_ci } else { 47951cb0ef41Sopenharmony_ci if (kArchEndian == kLittle) { 47961cb0ef41Sopenharmony_ci Move(v0, v1, src); 47971cb0ef41Sopenharmony_ci } else { 47981cb0ef41Sopenharmony_ci Move(v1, v0, src); 47991cb0ef41Sopenharmony_ci } 48001cb0ef41Sopenharmony_ci } 48011cb0ef41Sopenharmony_ci} 48021cb0ef41Sopenharmony_ci 48031cb0ef41Sopenharmony_civoid TurboAssembler::MovToFloatParameters(DoubleRegister src1, 48041cb0ef41Sopenharmony_ci DoubleRegister src2) { 48051cb0ef41Sopenharmony_ci if (!IsMipsSoftFloatABI) { 48061cb0ef41Sopenharmony_ci const DoubleRegister fparg2 = f13; 48071cb0ef41Sopenharmony_ci if (src2 == f12) { 48081cb0ef41Sopenharmony_ci DCHECK(src1 != fparg2); 48091cb0ef41Sopenharmony_ci Move(fparg2, src2); 48101cb0ef41Sopenharmony_ci Move(f12, src1); 48111cb0ef41Sopenharmony_ci } else { 48121cb0ef41Sopenharmony_ci Move(f12, src1); 48131cb0ef41Sopenharmony_ci Move(fparg2, src2); 48141cb0ef41Sopenharmony_ci } 48151cb0ef41Sopenharmony_ci } else { 48161cb0ef41Sopenharmony_ci if (kArchEndian == kLittle) { 48171cb0ef41Sopenharmony_ci Move(a0, a1, src1); 48181cb0ef41Sopenharmony_ci Move(a2, a3, src2); 48191cb0ef41Sopenharmony_ci } else { 48201cb0ef41Sopenharmony_ci Move(a1, a0, src1); 48211cb0ef41Sopenharmony_ci Move(a3, a2, src2); 48221cb0ef41Sopenharmony_ci } 48231cb0ef41Sopenharmony_ci } 48241cb0ef41Sopenharmony_ci} 48251cb0ef41Sopenharmony_ci 48261cb0ef41Sopenharmony_ci// ----------------------------------------------------------------------------- 48271cb0ef41Sopenharmony_ci// JavaScript invokes. 48281cb0ef41Sopenharmony_ci 48291cb0ef41Sopenharmony_civoid MacroAssembler::LoadStackLimit(Register destination, StackLimitKind kind) { 48301cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 48311cb0ef41Sopenharmony_ci DCHECK(root_array_available()); 48321cb0ef41Sopenharmony_ci Isolate* isolate = this->isolate(); 48331cb0ef41Sopenharmony_ci ExternalReference limit = 48341cb0ef41Sopenharmony_ci kind == StackLimitKind::kRealStackLimit 48351cb0ef41Sopenharmony_ci ? ExternalReference::address_of_real_jslimit(isolate) 48361cb0ef41Sopenharmony_ci : ExternalReference::address_of_jslimit(isolate); 48371cb0ef41Sopenharmony_ci DCHECK(TurboAssembler::IsAddressableThroughRootRegister(isolate, limit)); 48381cb0ef41Sopenharmony_ci 48391cb0ef41Sopenharmony_ci intptr_t offset = 48401cb0ef41Sopenharmony_ci TurboAssembler::RootRegisterOffsetForExternalReference(isolate, limit); 48411cb0ef41Sopenharmony_ci CHECK(is_int32(offset)); 48421cb0ef41Sopenharmony_ci Ld(destination, MemOperand(kRootRegister, static_cast<int32_t>(offset))); 48431cb0ef41Sopenharmony_ci} 48441cb0ef41Sopenharmony_ci 48451cb0ef41Sopenharmony_civoid MacroAssembler::StackOverflowCheck(Register num_args, Register scratch1, 48461cb0ef41Sopenharmony_ci Register scratch2, 48471cb0ef41Sopenharmony_ci Label* stack_overflow) { 48481cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 48491cb0ef41Sopenharmony_ci // Check the stack for overflow. We are not trying to catch 48501cb0ef41Sopenharmony_ci // interruptions (e.g. debug break and preemption) here, so the "real stack 48511cb0ef41Sopenharmony_ci // limit" is checked. 48521cb0ef41Sopenharmony_ci 48531cb0ef41Sopenharmony_ci LoadStackLimit(scratch1, StackLimitKind::kRealStackLimit); 48541cb0ef41Sopenharmony_ci // Make scratch1 the space we have left. The stack might already be overflowed 48551cb0ef41Sopenharmony_ci // here which will cause scratch1 to become negative. 48561cb0ef41Sopenharmony_ci dsubu(scratch1, sp, scratch1); 48571cb0ef41Sopenharmony_ci // Check if the arguments will overflow the stack. 48581cb0ef41Sopenharmony_ci dsll(scratch2, num_args, kPointerSizeLog2); 48591cb0ef41Sopenharmony_ci // Signed comparison. 48601cb0ef41Sopenharmony_ci Branch(stack_overflow, le, scratch1, Operand(scratch2)); 48611cb0ef41Sopenharmony_ci} 48621cb0ef41Sopenharmony_ci 48631cb0ef41Sopenharmony_civoid MacroAssembler::InvokePrologue(Register expected_parameter_count, 48641cb0ef41Sopenharmony_ci Register actual_parameter_count, 48651cb0ef41Sopenharmony_ci Label* done, InvokeType type) { 48661cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 48671cb0ef41Sopenharmony_ci Label regular_invoke; 48681cb0ef41Sopenharmony_ci 48691cb0ef41Sopenharmony_ci // a0: actual arguments count 48701cb0ef41Sopenharmony_ci // a1: function (passed through to callee) 48711cb0ef41Sopenharmony_ci // a2: expected arguments count 48721cb0ef41Sopenharmony_ci 48731cb0ef41Sopenharmony_ci DCHECK_EQ(actual_parameter_count, a0); 48741cb0ef41Sopenharmony_ci DCHECK_EQ(expected_parameter_count, a2); 48751cb0ef41Sopenharmony_ci 48761cb0ef41Sopenharmony_ci // If the expected parameter count is equal to the adaptor sentinel, no need 48771cb0ef41Sopenharmony_ci // to push undefined value as arguments. 48781cb0ef41Sopenharmony_ci if (kDontAdaptArgumentsSentinel != 0) { 48791cb0ef41Sopenharmony_ci Branch(®ular_invoke, eq, expected_parameter_count, 48801cb0ef41Sopenharmony_ci Operand(kDontAdaptArgumentsSentinel)); 48811cb0ef41Sopenharmony_ci } 48821cb0ef41Sopenharmony_ci 48831cb0ef41Sopenharmony_ci // If overapplication or if the actual argument count is equal to the 48841cb0ef41Sopenharmony_ci // formal parameter count, no need to push extra undefined values. 48851cb0ef41Sopenharmony_ci Dsubu(expected_parameter_count, expected_parameter_count, 48861cb0ef41Sopenharmony_ci actual_parameter_count); 48871cb0ef41Sopenharmony_ci Branch(®ular_invoke, le, expected_parameter_count, Operand(zero_reg)); 48881cb0ef41Sopenharmony_ci 48891cb0ef41Sopenharmony_ci Label stack_overflow; 48901cb0ef41Sopenharmony_ci StackOverflowCheck(expected_parameter_count, t0, t1, &stack_overflow); 48911cb0ef41Sopenharmony_ci // Underapplication. Move the arguments already in the stack, including the 48921cb0ef41Sopenharmony_ci // receiver and the return address. 48931cb0ef41Sopenharmony_ci { 48941cb0ef41Sopenharmony_ci Label copy; 48951cb0ef41Sopenharmony_ci Register src = a6, dest = a7; 48961cb0ef41Sopenharmony_ci mov(src, sp); 48971cb0ef41Sopenharmony_ci dsll(t0, expected_parameter_count, kSystemPointerSizeLog2); 48981cb0ef41Sopenharmony_ci Dsubu(sp, sp, Operand(t0)); 48991cb0ef41Sopenharmony_ci // Update stack pointer. 49001cb0ef41Sopenharmony_ci mov(dest, sp); 49011cb0ef41Sopenharmony_ci mov(t0, actual_parameter_count); 49021cb0ef41Sopenharmony_ci bind(©); 49031cb0ef41Sopenharmony_ci Ld(t1, MemOperand(src, 0)); 49041cb0ef41Sopenharmony_ci Sd(t1, MemOperand(dest, 0)); 49051cb0ef41Sopenharmony_ci Dsubu(t0, t0, Operand(1)); 49061cb0ef41Sopenharmony_ci Daddu(src, src, Operand(kSystemPointerSize)); 49071cb0ef41Sopenharmony_ci Daddu(dest, dest, Operand(kSystemPointerSize)); 49081cb0ef41Sopenharmony_ci Branch(©, gt, t0, Operand(zero_reg)); 49091cb0ef41Sopenharmony_ci } 49101cb0ef41Sopenharmony_ci 49111cb0ef41Sopenharmony_ci // Fill remaining expected arguments with undefined values. 49121cb0ef41Sopenharmony_ci LoadRoot(t0, RootIndex::kUndefinedValue); 49131cb0ef41Sopenharmony_ci { 49141cb0ef41Sopenharmony_ci Label loop; 49151cb0ef41Sopenharmony_ci bind(&loop); 49161cb0ef41Sopenharmony_ci Sd(t0, MemOperand(a7, 0)); 49171cb0ef41Sopenharmony_ci Dsubu(expected_parameter_count, expected_parameter_count, Operand(1)); 49181cb0ef41Sopenharmony_ci Daddu(a7, a7, Operand(kSystemPointerSize)); 49191cb0ef41Sopenharmony_ci Branch(&loop, gt, expected_parameter_count, Operand(zero_reg)); 49201cb0ef41Sopenharmony_ci } 49211cb0ef41Sopenharmony_ci b(®ular_invoke); 49221cb0ef41Sopenharmony_ci nop(); 49231cb0ef41Sopenharmony_ci 49241cb0ef41Sopenharmony_ci bind(&stack_overflow); 49251cb0ef41Sopenharmony_ci { 49261cb0ef41Sopenharmony_ci FrameScope frame( 49271cb0ef41Sopenharmony_ci this, has_frame() ? StackFrame::NO_FRAME_TYPE : StackFrame::INTERNAL); 49281cb0ef41Sopenharmony_ci CallRuntime(Runtime::kThrowStackOverflow); 49291cb0ef41Sopenharmony_ci break_(0xCC); 49301cb0ef41Sopenharmony_ci } 49311cb0ef41Sopenharmony_ci 49321cb0ef41Sopenharmony_ci bind(®ular_invoke); 49331cb0ef41Sopenharmony_ci} 49341cb0ef41Sopenharmony_ci 49351cb0ef41Sopenharmony_civoid MacroAssembler::CheckDebugHook(Register fun, Register new_target, 49361cb0ef41Sopenharmony_ci Register expected_parameter_count, 49371cb0ef41Sopenharmony_ci Register actual_parameter_count) { 49381cb0ef41Sopenharmony_ci Label skip_hook; 49391cb0ef41Sopenharmony_ci 49401cb0ef41Sopenharmony_ci li(t0, ExternalReference::debug_hook_on_function_call_address(isolate())); 49411cb0ef41Sopenharmony_ci Lb(t0, MemOperand(t0)); 49421cb0ef41Sopenharmony_ci Branch(&skip_hook, eq, t0, Operand(zero_reg)); 49431cb0ef41Sopenharmony_ci 49441cb0ef41Sopenharmony_ci { 49451cb0ef41Sopenharmony_ci // Load receiver to pass it later to DebugOnFunctionCall hook. 49461cb0ef41Sopenharmony_ci LoadReceiver(t0, actual_parameter_count); 49471cb0ef41Sopenharmony_ci 49481cb0ef41Sopenharmony_ci FrameScope frame( 49491cb0ef41Sopenharmony_ci this, has_frame() ? StackFrame::NO_FRAME_TYPE : StackFrame::INTERNAL); 49501cb0ef41Sopenharmony_ci SmiTag(expected_parameter_count); 49511cb0ef41Sopenharmony_ci Push(expected_parameter_count); 49521cb0ef41Sopenharmony_ci 49531cb0ef41Sopenharmony_ci SmiTag(actual_parameter_count); 49541cb0ef41Sopenharmony_ci Push(actual_parameter_count); 49551cb0ef41Sopenharmony_ci 49561cb0ef41Sopenharmony_ci if (new_target.is_valid()) { 49571cb0ef41Sopenharmony_ci Push(new_target); 49581cb0ef41Sopenharmony_ci } 49591cb0ef41Sopenharmony_ci Push(fun); 49601cb0ef41Sopenharmony_ci Push(fun); 49611cb0ef41Sopenharmony_ci Push(t0); 49621cb0ef41Sopenharmony_ci CallRuntime(Runtime::kDebugOnFunctionCall); 49631cb0ef41Sopenharmony_ci Pop(fun); 49641cb0ef41Sopenharmony_ci if (new_target.is_valid()) { 49651cb0ef41Sopenharmony_ci Pop(new_target); 49661cb0ef41Sopenharmony_ci } 49671cb0ef41Sopenharmony_ci 49681cb0ef41Sopenharmony_ci Pop(actual_parameter_count); 49691cb0ef41Sopenharmony_ci SmiUntag(actual_parameter_count); 49701cb0ef41Sopenharmony_ci 49711cb0ef41Sopenharmony_ci Pop(expected_parameter_count); 49721cb0ef41Sopenharmony_ci SmiUntag(expected_parameter_count); 49731cb0ef41Sopenharmony_ci } 49741cb0ef41Sopenharmony_ci bind(&skip_hook); 49751cb0ef41Sopenharmony_ci} 49761cb0ef41Sopenharmony_ci 49771cb0ef41Sopenharmony_civoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target, 49781cb0ef41Sopenharmony_ci Register expected_parameter_count, 49791cb0ef41Sopenharmony_ci Register actual_parameter_count, 49801cb0ef41Sopenharmony_ci InvokeType type) { 49811cb0ef41Sopenharmony_ci // You can't call a function without a valid frame. 49821cb0ef41Sopenharmony_ci DCHECK_IMPLIES(type == InvokeType::kCall, has_frame()); 49831cb0ef41Sopenharmony_ci DCHECK_EQ(function, a1); 49841cb0ef41Sopenharmony_ci DCHECK_IMPLIES(new_target.is_valid(), new_target == a3); 49851cb0ef41Sopenharmony_ci 49861cb0ef41Sopenharmony_ci // On function call, call into the debugger if necessary. 49871cb0ef41Sopenharmony_ci CheckDebugHook(function, new_target, expected_parameter_count, 49881cb0ef41Sopenharmony_ci actual_parameter_count); 49891cb0ef41Sopenharmony_ci 49901cb0ef41Sopenharmony_ci // Clear the new.target register if not given. 49911cb0ef41Sopenharmony_ci if (!new_target.is_valid()) { 49921cb0ef41Sopenharmony_ci LoadRoot(a3, RootIndex::kUndefinedValue); 49931cb0ef41Sopenharmony_ci } 49941cb0ef41Sopenharmony_ci 49951cb0ef41Sopenharmony_ci Label done; 49961cb0ef41Sopenharmony_ci InvokePrologue(expected_parameter_count, actual_parameter_count, &done, type); 49971cb0ef41Sopenharmony_ci // We call indirectly through the code field in the function to 49981cb0ef41Sopenharmony_ci // allow recompilation to take effect without changing any of the 49991cb0ef41Sopenharmony_ci // call sites. 50001cb0ef41Sopenharmony_ci Register code = kJavaScriptCallCodeStartRegister; 50011cb0ef41Sopenharmony_ci Ld(code, FieldMemOperand(function, JSFunction::kCodeOffset)); 50021cb0ef41Sopenharmony_ci switch (type) { 50031cb0ef41Sopenharmony_ci case InvokeType::kCall: 50041cb0ef41Sopenharmony_ci Daddu(code, code, Operand(Code::kHeaderSize - kHeapObjectTag)); 50051cb0ef41Sopenharmony_ci Call(code); 50061cb0ef41Sopenharmony_ci break; 50071cb0ef41Sopenharmony_ci case InvokeType::kJump: 50081cb0ef41Sopenharmony_ci Daddu(code, code, Operand(Code::kHeaderSize - kHeapObjectTag)); 50091cb0ef41Sopenharmony_ci Jump(code); 50101cb0ef41Sopenharmony_ci break; 50111cb0ef41Sopenharmony_ci } 50121cb0ef41Sopenharmony_ci 50131cb0ef41Sopenharmony_ci // Continue here if InvokePrologue does handle the invocation due to 50141cb0ef41Sopenharmony_ci // mismatched parameter counts. 50151cb0ef41Sopenharmony_ci bind(&done); 50161cb0ef41Sopenharmony_ci} 50171cb0ef41Sopenharmony_ci 50181cb0ef41Sopenharmony_civoid MacroAssembler::InvokeFunctionWithNewTarget( 50191cb0ef41Sopenharmony_ci Register function, Register new_target, Register actual_parameter_count, 50201cb0ef41Sopenharmony_ci InvokeType type) { 50211cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 50221cb0ef41Sopenharmony_ci // You can't call a function without a valid frame. 50231cb0ef41Sopenharmony_ci DCHECK_IMPLIES(type == InvokeType::kCall, has_frame()); 50241cb0ef41Sopenharmony_ci 50251cb0ef41Sopenharmony_ci // Contract with called JS functions requires that function is passed in a1. 50261cb0ef41Sopenharmony_ci DCHECK_EQ(function, a1); 50271cb0ef41Sopenharmony_ci Register expected_parameter_count = a2; 50281cb0ef41Sopenharmony_ci Register temp_reg = t0; 50291cb0ef41Sopenharmony_ci Ld(temp_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 50301cb0ef41Sopenharmony_ci Ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); 50311cb0ef41Sopenharmony_ci // The argument count is stored as uint16_t 50321cb0ef41Sopenharmony_ci Lhu(expected_parameter_count, 50331cb0ef41Sopenharmony_ci FieldMemOperand(temp_reg, 50341cb0ef41Sopenharmony_ci SharedFunctionInfo::kFormalParameterCountOffset)); 50351cb0ef41Sopenharmony_ci 50361cb0ef41Sopenharmony_ci InvokeFunctionCode(a1, new_target, expected_parameter_count, 50371cb0ef41Sopenharmony_ci actual_parameter_count, type); 50381cb0ef41Sopenharmony_ci} 50391cb0ef41Sopenharmony_ci 50401cb0ef41Sopenharmony_civoid MacroAssembler::InvokeFunction(Register function, 50411cb0ef41Sopenharmony_ci Register expected_parameter_count, 50421cb0ef41Sopenharmony_ci Register actual_parameter_count, 50431cb0ef41Sopenharmony_ci InvokeType type) { 50441cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 50451cb0ef41Sopenharmony_ci // You can't call a function without a valid frame. 50461cb0ef41Sopenharmony_ci DCHECK_IMPLIES(type == InvokeType::kCall, has_frame()); 50471cb0ef41Sopenharmony_ci 50481cb0ef41Sopenharmony_ci // Contract with called JS functions requires that function is passed in a1. 50491cb0ef41Sopenharmony_ci DCHECK_EQ(function, a1); 50501cb0ef41Sopenharmony_ci 50511cb0ef41Sopenharmony_ci // Get the function and setup the context. 50521cb0ef41Sopenharmony_ci Ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); 50531cb0ef41Sopenharmony_ci 50541cb0ef41Sopenharmony_ci InvokeFunctionCode(a1, no_reg, expected_parameter_count, 50551cb0ef41Sopenharmony_ci actual_parameter_count, type); 50561cb0ef41Sopenharmony_ci} 50571cb0ef41Sopenharmony_ci 50581cb0ef41Sopenharmony_ci// --------------------------------------------------------------------------- 50591cb0ef41Sopenharmony_ci// Support functions. 50601cb0ef41Sopenharmony_ci 50611cb0ef41Sopenharmony_civoid MacroAssembler::GetObjectType(Register object, Register map, 50621cb0ef41Sopenharmony_ci Register type_reg) { 50631cb0ef41Sopenharmony_ci LoadMap(map, object); 50641cb0ef41Sopenharmony_ci Lhu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); 50651cb0ef41Sopenharmony_ci} 50661cb0ef41Sopenharmony_ci 50671cb0ef41Sopenharmony_civoid MacroAssembler::GetInstanceTypeRange(Register map, Register type_reg, 50681cb0ef41Sopenharmony_ci InstanceType lower_limit, 50691cb0ef41Sopenharmony_ci Register range) { 50701cb0ef41Sopenharmony_ci Lhu(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset)); 50711cb0ef41Sopenharmony_ci Dsubu(range, type_reg, Operand(lower_limit)); 50721cb0ef41Sopenharmony_ci} 50731cb0ef41Sopenharmony_ci 50741cb0ef41Sopenharmony_ci// ----------------------------------------------------------------------------- 50751cb0ef41Sopenharmony_ci// Runtime calls. 50761cb0ef41Sopenharmony_ci 50771cb0ef41Sopenharmony_civoid TurboAssembler::DaddOverflow(Register dst, Register left, 50781cb0ef41Sopenharmony_ci const Operand& right, Register overflow) { 50791cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 50801cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 50811cb0ef41Sopenharmony_ci Register right_reg = no_reg; 50821cb0ef41Sopenharmony_ci Register scratch = t8; 50831cb0ef41Sopenharmony_ci if (!right.is_reg()) { 50841cb0ef41Sopenharmony_ci li(at, Operand(right)); 50851cb0ef41Sopenharmony_ci right_reg = at; 50861cb0ef41Sopenharmony_ci } else { 50871cb0ef41Sopenharmony_ci right_reg = right.rm(); 50881cb0ef41Sopenharmony_ci } 50891cb0ef41Sopenharmony_ci 50901cb0ef41Sopenharmony_ci DCHECK(left != scratch && right_reg != scratch && dst != scratch && 50911cb0ef41Sopenharmony_ci overflow != scratch); 50921cb0ef41Sopenharmony_ci DCHECK(overflow != left && overflow != right_reg); 50931cb0ef41Sopenharmony_ci 50941cb0ef41Sopenharmony_ci if (dst == left || dst == right_reg) { 50951cb0ef41Sopenharmony_ci daddu(scratch, left, right_reg); 50961cb0ef41Sopenharmony_ci xor_(overflow, scratch, left); 50971cb0ef41Sopenharmony_ci xor_(at, scratch, right_reg); 50981cb0ef41Sopenharmony_ci and_(overflow, overflow, at); 50991cb0ef41Sopenharmony_ci mov(dst, scratch); 51001cb0ef41Sopenharmony_ci } else { 51011cb0ef41Sopenharmony_ci daddu(dst, left, right_reg); 51021cb0ef41Sopenharmony_ci xor_(overflow, dst, left); 51031cb0ef41Sopenharmony_ci xor_(at, dst, right_reg); 51041cb0ef41Sopenharmony_ci and_(overflow, overflow, at); 51051cb0ef41Sopenharmony_ci } 51061cb0ef41Sopenharmony_ci} 51071cb0ef41Sopenharmony_ci 51081cb0ef41Sopenharmony_civoid TurboAssembler::DsubOverflow(Register dst, Register left, 51091cb0ef41Sopenharmony_ci const Operand& right, Register overflow) { 51101cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 51111cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 51121cb0ef41Sopenharmony_ci Register right_reg = no_reg; 51131cb0ef41Sopenharmony_ci Register scratch = t8; 51141cb0ef41Sopenharmony_ci if (!right.is_reg()) { 51151cb0ef41Sopenharmony_ci li(at, Operand(right)); 51161cb0ef41Sopenharmony_ci right_reg = at; 51171cb0ef41Sopenharmony_ci } else { 51181cb0ef41Sopenharmony_ci right_reg = right.rm(); 51191cb0ef41Sopenharmony_ci } 51201cb0ef41Sopenharmony_ci 51211cb0ef41Sopenharmony_ci DCHECK(left != scratch && right_reg != scratch && dst != scratch && 51221cb0ef41Sopenharmony_ci overflow != scratch); 51231cb0ef41Sopenharmony_ci DCHECK(overflow != left && overflow != right_reg); 51241cb0ef41Sopenharmony_ci 51251cb0ef41Sopenharmony_ci if (dst == left || dst == right_reg) { 51261cb0ef41Sopenharmony_ci dsubu(scratch, left, right_reg); 51271cb0ef41Sopenharmony_ci xor_(overflow, left, scratch); 51281cb0ef41Sopenharmony_ci xor_(at, left, right_reg); 51291cb0ef41Sopenharmony_ci and_(overflow, overflow, at); 51301cb0ef41Sopenharmony_ci mov(dst, scratch); 51311cb0ef41Sopenharmony_ci } else { 51321cb0ef41Sopenharmony_ci dsubu(dst, left, right_reg); 51331cb0ef41Sopenharmony_ci xor_(overflow, left, dst); 51341cb0ef41Sopenharmony_ci xor_(at, left, right_reg); 51351cb0ef41Sopenharmony_ci and_(overflow, overflow, at); 51361cb0ef41Sopenharmony_ci } 51371cb0ef41Sopenharmony_ci} 51381cb0ef41Sopenharmony_ci 51391cb0ef41Sopenharmony_civoid TurboAssembler::MulOverflow(Register dst, Register left, 51401cb0ef41Sopenharmony_ci const Operand& right, Register overflow) { 51411cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 51421cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 51431cb0ef41Sopenharmony_ci Register right_reg = no_reg; 51441cb0ef41Sopenharmony_ci Register scratch = t8; 51451cb0ef41Sopenharmony_ci if (!right.is_reg()) { 51461cb0ef41Sopenharmony_ci li(at, Operand(right)); 51471cb0ef41Sopenharmony_ci right_reg = at; 51481cb0ef41Sopenharmony_ci } else { 51491cb0ef41Sopenharmony_ci right_reg = right.rm(); 51501cb0ef41Sopenharmony_ci } 51511cb0ef41Sopenharmony_ci 51521cb0ef41Sopenharmony_ci DCHECK(left != scratch && right_reg != scratch && dst != scratch && 51531cb0ef41Sopenharmony_ci overflow != scratch); 51541cb0ef41Sopenharmony_ci DCHECK(overflow != left && overflow != right_reg); 51551cb0ef41Sopenharmony_ci 51561cb0ef41Sopenharmony_ci if (dst == left || dst == right_reg) { 51571cb0ef41Sopenharmony_ci Mul(scratch, left, right_reg); 51581cb0ef41Sopenharmony_ci Mulh(overflow, left, right_reg); 51591cb0ef41Sopenharmony_ci mov(dst, scratch); 51601cb0ef41Sopenharmony_ci } else { 51611cb0ef41Sopenharmony_ci Mul(dst, left, right_reg); 51621cb0ef41Sopenharmony_ci Mulh(overflow, left, right_reg); 51631cb0ef41Sopenharmony_ci } 51641cb0ef41Sopenharmony_ci 51651cb0ef41Sopenharmony_ci dsra32(scratch, dst, 0); 51661cb0ef41Sopenharmony_ci xor_(overflow, overflow, scratch); 51671cb0ef41Sopenharmony_ci} 51681cb0ef41Sopenharmony_ci 51691cb0ef41Sopenharmony_civoid MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments, 51701cb0ef41Sopenharmony_ci SaveFPRegsMode save_doubles) { 51711cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 51721cb0ef41Sopenharmony_ci // All parameters are on the stack. v0 has the return value after call. 51731cb0ef41Sopenharmony_ci 51741cb0ef41Sopenharmony_ci // If the expected number of arguments of the runtime function is 51751cb0ef41Sopenharmony_ci // constant, we check that the actual number of arguments match the 51761cb0ef41Sopenharmony_ci // expectation. 51771cb0ef41Sopenharmony_ci CHECK(f->nargs < 0 || f->nargs == num_arguments); 51781cb0ef41Sopenharmony_ci 51791cb0ef41Sopenharmony_ci // TODO(1236192): Most runtime routines don't need the number of 51801cb0ef41Sopenharmony_ci // arguments passed in because it is constant. At some point we 51811cb0ef41Sopenharmony_ci // should remove this need and make the runtime routine entry code 51821cb0ef41Sopenharmony_ci // smarter. 51831cb0ef41Sopenharmony_ci PrepareCEntryArgs(num_arguments); 51841cb0ef41Sopenharmony_ci PrepareCEntryFunction(ExternalReference::Create(f)); 51851cb0ef41Sopenharmony_ci Handle<Code> code = 51861cb0ef41Sopenharmony_ci CodeFactory::CEntry(isolate(), f->result_size, save_doubles); 51871cb0ef41Sopenharmony_ci Call(code, RelocInfo::CODE_TARGET); 51881cb0ef41Sopenharmony_ci} 51891cb0ef41Sopenharmony_ci 51901cb0ef41Sopenharmony_civoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) { 51911cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 51921cb0ef41Sopenharmony_ci const Runtime::Function* function = Runtime::FunctionForId(fid); 51931cb0ef41Sopenharmony_ci DCHECK_EQ(1, function->result_size); 51941cb0ef41Sopenharmony_ci if (function->nargs >= 0) { 51951cb0ef41Sopenharmony_ci PrepareCEntryArgs(function->nargs); 51961cb0ef41Sopenharmony_ci } 51971cb0ef41Sopenharmony_ci JumpToExternalReference(ExternalReference::Create(fid)); 51981cb0ef41Sopenharmony_ci} 51991cb0ef41Sopenharmony_ci 52001cb0ef41Sopenharmony_civoid MacroAssembler::JumpToExternalReference(const ExternalReference& builtin, 52011cb0ef41Sopenharmony_ci BranchDelaySlot bd, 52021cb0ef41Sopenharmony_ci bool builtin_exit_frame) { 52031cb0ef41Sopenharmony_ci PrepareCEntryFunction(builtin); 52041cb0ef41Sopenharmony_ci Handle<Code> code = CodeFactory::CEntry(isolate(), 1, SaveFPRegsMode::kIgnore, 52051cb0ef41Sopenharmony_ci ArgvMode::kStack, builtin_exit_frame); 52061cb0ef41Sopenharmony_ci Jump(code, RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg), bd); 52071cb0ef41Sopenharmony_ci} 52081cb0ef41Sopenharmony_ci 52091cb0ef41Sopenharmony_civoid MacroAssembler::JumpToOffHeapInstructionStream(Address entry) { 52101cb0ef41Sopenharmony_ci li(kOffHeapTrampolineRegister, Operand(entry, RelocInfo::OFF_HEAP_TARGET)); 52111cb0ef41Sopenharmony_ci Jump(kOffHeapTrampolineRegister); 52121cb0ef41Sopenharmony_ci} 52131cb0ef41Sopenharmony_ci 52141cb0ef41Sopenharmony_civoid MacroAssembler::LoadWeakValue(Register out, Register in, 52151cb0ef41Sopenharmony_ci Label* target_if_cleared) { 52161cb0ef41Sopenharmony_ci Branch(target_if_cleared, eq, in, Operand(kClearedWeakHeapObjectLower32)); 52171cb0ef41Sopenharmony_ci 52181cb0ef41Sopenharmony_ci And(out, in, Operand(~kWeakHeapObjectMask)); 52191cb0ef41Sopenharmony_ci} 52201cb0ef41Sopenharmony_ci 52211cb0ef41Sopenharmony_civoid MacroAssembler::EmitIncrementCounter(StatsCounter* counter, int value, 52221cb0ef41Sopenharmony_ci Register scratch1, 52231cb0ef41Sopenharmony_ci Register scratch2) { 52241cb0ef41Sopenharmony_ci DCHECK_GT(value, 0); 52251cb0ef41Sopenharmony_ci if (FLAG_native_code_counters && counter->Enabled()) { 52261cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 52271cb0ef41Sopenharmony_ci // This operation has to be exactly 32-bit wide in case the external 52281cb0ef41Sopenharmony_ci // reference table redirects the counter to a uint32_t dummy_stats_counter_ 52291cb0ef41Sopenharmony_ci // field. 52301cb0ef41Sopenharmony_ci li(scratch2, ExternalReference::Create(counter)); 52311cb0ef41Sopenharmony_ci Lw(scratch1, MemOperand(scratch2)); 52321cb0ef41Sopenharmony_ci Addu(scratch1, scratch1, Operand(value)); 52331cb0ef41Sopenharmony_ci Sw(scratch1, MemOperand(scratch2)); 52341cb0ef41Sopenharmony_ci } 52351cb0ef41Sopenharmony_ci} 52361cb0ef41Sopenharmony_ci 52371cb0ef41Sopenharmony_civoid MacroAssembler::EmitDecrementCounter(StatsCounter* counter, int value, 52381cb0ef41Sopenharmony_ci Register scratch1, 52391cb0ef41Sopenharmony_ci Register scratch2) { 52401cb0ef41Sopenharmony_ci DCHECK_GT(value, 0); 52411cb0ef41Sopenharmony_ci if (FLAG_native_code_counters && counter->Enabled()) { 52421cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 52431cb0ef41Sopenharmony_ci // This operation has to be exactly 32-bit wide in case the external 52441cb0ef41Sopenharmony_ci // reference table redirects the counter to a uint32_t dummy_stats_counter_ 52451cb0ef41Sopenharmony_ci // field. 52461cb0ef41Sopenharmony_ci li(scratch2, ExternalReference::Create(counter)); 52471cb0ef41Sopenharmony_ci Lw(scratch1, MemOperand(scratch2)); 52481cb0ef41Sopenharmony_ci Subu(scratch1, scratch1, Operand(value)); 52491cb0ef41Sopenharmony_ci Sw(scratch1, MemOperand(scratch2)); 52501cb0ef41Sopenharmony_ci } 52511cb0ef41Sopenharmony_ci} 52521cb0ef41Sopenharmony_ci 52531cb0ef41Sopenharmony_ci// ----------------------------------------------------------------------------- 52541cb0ef41Sopenharmony_ci// Debugging. 52551cb0ef41Sopenharmony_ci 52561cb0ef41Sopenharmony_civoid TurboAssembler::Trap() { stop(); } 52571cb0ef41Sopenharmony_civoid TurboAssembler::DebugBreak() { stop(); } 52581cb0ef41Sopenharmony_ci 52591cb0ef41Sopenharmony_civoid TurboAssembler::Assert(Condition cc, AbortReason reason, Register rs, 52601cb0ef41Sopenharmony_ci Operand rt) { 52611cb0ef41Sopenharmony_ci if (FLAG_debug_code) Check(cc, reason, rs, rt); 52621cb0ef41Sopenharmony_ci} 52631cb0ef41Sopenharmony_ci 52641cb0ef41Sopenharmony_civoid TurboAssembler::Check(Condition cc, AbortReason reason, Register rs, 52651cb0ef41Sopenharmony_ci Operand rt) { 52661cb0ef41Sopenharmony_ci Label L; 52671cb0ef41Sopenharmony_ci Branch(&L, cc, rs, rt); 52681cb0ef41Sopenharmony_ci Abort(reason); 52691cb0ef41Sopenharmony_ci // Will not return here. 52701cb0ef41Sopenharmony_ci bind(&L); 52711cb0ef41Sopenharmony_ci} 52721cb0ef41Sopenharmony_ci 52731cb0ef41Sopenharmony_civoid TurboAssembler::Abort(AbortReason reason) { 52741cb0ef41Sopenharmony_ci Label abort_start; 52751cb0ef41Sopenharmony_ci bind(&abort_start); 52761cb0ef41Sopenharmony_ci if (FLAG_code_comments) { 52771cb0ef41Sopenharmony_ci const char* msg = GetAbortReason(reason); 52781cb0ef41Sopenharmony_ci RecordComment("Abort message: "); 52791cb0ef41Sopenharmony_ci RecordComment(msg); 52801cb0ef41Sopenharmony_ci } 52811cb0ef41Sopenharmony_ci 52821cb0ef41Sopenharmony_ci // Avoid emitting call to builtin if requested. 52831cb0ef41Sopenharmony_ci if (trap_on_abort()) { 52841cb0ef41Sopenharmony_ci stop(); 52851cb0ef41Sopenharmony_ci return; 52861cb0ef41Sopenharmony_ci } 52871cb0ef41Sopenharmony_ci 52881cb0ef41Sopenharmony_ci if (should_abort_hard()) { 52891cb0ef41Sopenharmony_ci // We don't care if we constructed a frame. Just pretend we did. 52901cb0ef41Sopenharmony_ci FrameScope assume_frame(this, StackFrame::NO_FRAME_TYPE); 52911cb0ef41Sopenharmony_ci PrepareCallCFunction(0, a0); 52921cb0ef41Sopenharmony_ci li(a0, Operand(static_cast<int>(reason))); 52931cb0ef41Sopenharmony_ci CallCFunction(ExternalReference::abort_with_reason(), 1); 52941cb0ef41Sopenharmony_ci return; 52951cb0ef41Sopenharmony_ci } 52961cb0ef41Sopenharmony_ci 52971cb0ef41Sopenharmony_ci Move(a0, Smi::FromInt(static_cast<int>(reason))); 52981cb0ef41Sopenharmony_ci 52991cb0ef41Sopenharmony_ci // Disable stub call restrictions to always allow calls to abort. 53001cb0ef41Sopenharmony_ci if (!has_frame()) { 53011cb0ef41Sopenharmony_ci // We don't actually want to generate a pile of code for this, so just 53021cb0ef41Sopenharmony_ci // claim there is a stack frame, without generating one. 53031cb0ef41Sopenharmony_ci FrameScope scope(this, StackFrame::NO_FRAME_TYPE); 53041cb0ef41Sopenharmony_ci Call(BUILTIN_CODE(isolate(), Abort), RelocInfo::CODE_TARGET); 53051cb0ef41Sopenharmony_ci } else { 53061cb0ef41Sopenharmony_ci Call(BUILTIN_CODE(isolate(), Abort), RelocInfo::CODE_TARGET); 53071cb0ef41Sopenharmony_ci } 53081cb0ef41Sopenharmony_ci // Will not return here. 53091cb0ef41Sopenharmony_ci if (is_trampoline_pool_blocked()) { 53101cb0ef41Sopenharmony_ci // If the calling code cares about the exact number of 53111cb0ef41Sopenharmony_ci // instructions generated, we insert padding here to keep the size 53121cb0ef41Sopenharmony_ci // of the Abort macro constant. 53131cb0ef41Sopenharmony_ci // Currently in debug mode with debug_code enabled the number of 53141cb0ef41Sopenharmony_ci // generated instructions is 10, so we use this as a maximum value. 53151cb0ef41Sopenharmony_ci static const int kExpectedAbortInstructions = 10; 53161cb0ef41Sopenharmony_ci int abort_instructions = InstructionsGeneratedSince(&abort_start); 53171cb0ef41Sopenharmony_ci DCHECK_LE(abort_instructions, kExpectedAbortInstructions); 53181cb0ef41Sopenharmony_ci while (abort_instructions++ < kExpectedAbortInstructions) { 53191cb0ef41Sopenharmony_ci nop(); 53201cb0ef41Sopenharmony_ci } 53211cb0ef41Sopenharmony_ci } 53221cb0ef41Sopenharmony_ci} 53231cb0ef41Sopenharmony_ci 53241cb0ef41Sopenharmony_civoid TurboAssembler::LoadMap(Register destination, Register object) { 53251cb0ef41Sopenharmony_ci Ld(destination, FieldMemOperand(object, HeapObject::kMapOffset)); 53261cb0ef41Sopenharmony_ci} 53271cb0ef41Sopenharmony_ci 53281cb0ef41Sopenharmony_civoid MacroAssembler::LoadNativeContextSlot(Register dst, int index) { 53291cb0ef41Sopenharmony_ci LoadMap(dst, cp); 53301cb0ef41Sopenharmony_ci Ld(dst, 53311cb0ef41Sopenharmony_ci FieldMemOperand(dst, Map::kConstructorOrBackPointerOrNativeContextOffset)); 53321cb0ef41Sopenharmony_ci Ld(dst, MemOperand(dst, Context::SlotOffset(index))); 53331cb0ef41Sopenharmony_ci} 53341cb0ef41Sopenharmony_ci 53351cb0ef41Sopenharmony_civoid TurboAssembler::StubPrologue(StackFrame::Type type) { 53361cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 53371cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 53381cb0ef41Sopenharmony_ci li(scratch, Operand(StackFrame::TypeToMarker(type))); 53391cb0ef41Sopenharmony_ci PushCommonFrame(scratch); 53401cb0ef41Sopenharmony_ci} 53411cb0ef41Sopenharmony_ci 53421cb0ef41Sopenharmony_civoid TurboAssembler::Prologue() { PushStandardFrame(a1); } 53431cb0ef41Sopenharmony_ci 53441cb0ef41Sopenharmony_civoid TurboAssembler::EnterFrame(StackFrame::Type type) { 53451cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 53461cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 53471cb0ef41Sopenharmony_ci Push(ra, fp); 53481cb0ef41Sopenharmony_ci Move(fp, sp); 53491cb0ef41Sopenharmony_ci if (!StackFrame::IsJavaScript(type)) { 53501cb0ef41Sopenharmony_ci li(kScratchReg, Operand(StackFrame::TypeToMarker(type))); 53511cb0ef41Sopenharmony_ci Push(kScratchReg); 53521cb0ef41Sopenharmony_ci } 53531cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 53541cb0ef41Sopenharmony_ci if (type == StackFrame::WASM) Push(kWasmInstanceRegister); 53551cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 53561cb0ef41Sopenharmony_ci} 53571cb0ef41Sopenharmony_ci 53581cb0ef41Sopenharmony_civoid TurboAssembler::LeaveFrame(StackFrame::Type type) { 53591cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 53601cb0ef41Sopenharmony_ci daddiu(sp, fp, 2 * kPointerSize); 53611cb0ef41Sopenharmony_ci Ld(ra, MemOperand(fp, 1 * kPointerSize)); 53621cb0ef41Sopenharmony_ci Ld(fp, MemOperand(fp, 0 * kPointerSize)); 53631cb0ef41Sopenharmony_ci} 53641cb0ef41Sopenharmony_ci 53651cb0ef41Sopenharmony_civoid MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space, 53661cb0ef41Sopenharmony_ci StackFrame::Type frame_type) { 53671cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 53681cb0ef41Sopenharmony_ci DCHECK(frame_type == StackFrame::EXIT || 53691cb0ef41Sopenharmony_ci frame_type == StackFrame::BUILTIN_EXIT); 53701cb0ef41Sopenharmony_ci 53711cb0ef41Sopenharmony_ci // Set up the frame structure on the stack. 53721cb0ef41Sopenharmony_ci STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); 53731cb0ef41Sopenharmony_ci STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); 53741cb0ef41Sopenharmony_ci STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); 53751cb0ef41Sopenharmony_ci 53761cb0ef41Sopenharmony_ci // This is how the stack will look: 53771cb0ef41Sopenharmony_ci // fp + 2 (==kCallerSPDisplacement) - old stack's end 53781cb0ef41Sopenharmony_ci // [fp + 1 (==kCallerPCOffset)] - saved old ra 53791cb0ef41Sopenharmony_ci // [fp + 0 (==kCallerFPOffset)] - saved old fp 53801cb0ef41Sopenharmony_ci // [fp - 1 StackFrame::EXIT Smi 53811cb0ef41Sopenharmony_ci // [fp - 2 (==kSPOffset)] - sp of the called function 53821cb0ef41Sopenharmony_ci // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the 53831cb0ef41Sopenharmony_ci // new stack (will contain saved ra) 53841cb0ef41Sopenharmony_ci 53851cb0ef41Sopenharmony_ci // Save registers and reserve room for saved entry sp. 53861cb0ef41Sopenharmony_ci daddiu(sp, sp, -2 * kPointerSize - ExitFrameConstants::kFixedFrameSizeFromFp); 53871cb0ef41Sopenharmony_ci Sd(ra, MemOperand(sp, 3 * kPointerSize)); 53881cb0ef41Sopenharmony_ci Sd(fp, MemOperand(sp, 2 * kPointerSize)); 53891cb0ef41Sopenharmony_ci { 53901cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 53911cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 53921cb0ef41Sopenharmony_ci li(scratch, Operand(StackFrame::TypeToMarker(frame_type))); 53931cb0ef41Sopenharmony_ci Sd(scratch, MemOperand(sp, 1 * kPointerSize)); 53941cb0ef41Sopenharmony_ci } 53951cb0ef41Sopenharmony_ci // Set up new frame pointer. 53961cb0ef41Sopenharmony_ci daddiu(fp, sp, ExitFrameConstants::kFixedFrameSizeFromFp); 53971cb0ef41Sopenharmony_ci 53981cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 53991cb0ef41Sopenharmony_ci Sd(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); 54001cb0ef41Sopenharmony_ci } 54011cb0ef41Sopenharmony_ci 54021cb0ef41Sopenharmony_ci { 54031cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 54041cb0ef41Sopenharmony_ci // Save the frame pointer and the context in top. 54051cb0ef41Sopenharmony_ci li(t8, ExternalReference::Create(IsolateAddressId::kCEntryFPAddress, 54061cb0ef41Sopenharmony_ci isolate())); 54071cb0ef41Sopenharmony_ci Sd(fp, MemOperand(t8)); 54081cb0ef41Sopenharmony_ci li(t8, 54091cb0ef41Sopenharmony_ci ExternalReference::Create(IsolateAddressId::kContextAddress, isolate())); 54101cb0ef41Sopenharmony_ci Sd(cp, MemOperand(t8)); 54111cb0ef41Sopenharmony_ci } 54121cb0ef41Sopenharmony_ci 54131cb0ef41Sopenharmony_ci const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); 54141cb0ef41Sopenharmony_ci if (save_doubles) { 54151cb0ef41Sopenharmony_ci // The stack is already aligned to 0 modulo 8 for stores with sdc1. 54161cb0ef41Sopenharmony_ci int kNumOfSavedRegisters = FPURegister::kNumRegisters / 2; 54171cb0ef41Sopenharmony_ci int space = kNumOfSavedRegisters * kDoubleSize; 54181cb0ef41Sopenharmony_ci Dsubu(sp, sp, Operand(space)); 54191cb0ef41Sopenharmony_ci // Remember: we only need to save every 2nd double FPU value. 54201cb0ef41Sopenharmony_ci for (int i = 0; i < kNumOfSavedRegisters; i++) { 54211cb0ef41Sopenharmony_ci FPURegister reg = FPURegister::from_code(2 * i); 54221cb0ef41Sopenharmony_ci Sdc1(reg, MemOperand(sp, i * kDoubleSize)); 54231cb0ef41Sopenharmony_ci } 54241cb0ef41Sopenharmony_ci } 54251cb0ef41Sopenharmony_ci 54261cb0ef41Sopenharmony_ci // Reserve place for the return address, stack space and an optional slot 54271cb0ef41Sopenharmony_ci // (used by DirectCEntry to hold the return value if a struct is 54281cb0ef41Sopenharmony_ci // returned) and align the frame preparing for calling the runtime function. 54291cb0ef41Sopenharmony_ci DCHECK_GE(stack_space, 0); 54301cb0ef41Sopenharmony_ci Dsubu(sp, sp, Operand((stack_space + 2) * kPointerSize)); 54311cb0ef41Sopenharmony_ci if (frame_alignment > 0) { 54321cb0ef41Sopenharmony_ci DCHECK(base::bits::IsPowerOfTwo(frame_alignment)); 54331cb0ef41Sopenharmony_ci And(sp, sp, Operand(-frame_alignment)); // Align stack. 54341cb0ef41Sopenharmony_ci } 54351cb0ef41Sopenharmony_ci 54361cb0ef41Sopenharmony_ci // Set the exit frame sp value to point just before the return address 54371cb0ef41Sopenharmony_ci // location. 54381cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 54391cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 54401cb0ef41Sopenharmony_ci daddiu(scratch, sp, kPointerSize); 54411cb0ef41Sopenharmony_ci Sd(scratch, MemOperand(fp, ExitFrameConstants::kSPOffset)); 54421cb0ef41Sopenharmony_ci} 54431cb0ef41Sopenharmony_ci 54441cb0ef41Sopenharmony_civoid MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, 54451cb0ef41Sopenharmony_ci bool do_return, 54461cb0ef41Sopenharmony_ci bool argument_count_is_length) { 54471cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 54481cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 54491cb0ef41Sopenharmony_ci // Optionally restore all double registers. 54501cb0ef41Sopenharmony_ci if (save_doubles) { 54511cb0ef41Sopenharmony_ci // Remember: we only need to restore every 2nd double FPU value. 54521cb0ef41Sopenharmony_ci int kNumOfSavedRegisters = FPURegister::kNumRegisters / 2; 54531cb0ef41Sopenharmony_ci Dsubu(t8, fp, 54541cb0ef41Sopenharmony_ci Operand(ExitFrameConstants::kFixedFrameSizeFromFp + 54551cb0ef41Sopenharmony_ci kNumOfSavedRegisters * kDoubleSize)); 54561cb0ef41Sopenharmony_ci for (int i = 0; i < kNumOfSavedRegisters; i++) { 54571cb0ef41Sopenharmony_ci FPURegister reg = FPURegister::from_code(2 * i); 54581cb0ef41Sopenharmony_ci Ldc1(reg, MemOperand(t8, i * kDoubleSize)); 54591cb0ef41Sopenharmony_ci } 54601cb0ef41Sopenharmony_ci } 54611cb0ef41Sopenharmony_ci 54621cb0ef41Sopenharmony_ci // Clear top frame. 54631cb0ef41Sopenharmony_ci li(t8, 54641cb0ef41Sopenharmony_ci ExternalReference::Create(IsolateAddressId::kCEntryFPAddress, isolate())); 54651cb0ef41Sopenharmony_ci Sd(zero_reg, MemOperand(t8)); 54661cb0ef41Sopenharmony_ci 54671cb0ef41Sopenharmony_ci // Restore current context from top and clear it in debug mode. 54681cb0ef41Sopenharmony_ci li(t8, 54691cb0ef41Sopenharmony_ci ExternalReference::Create(IsolateAddressId::kContextAddress, isolate())); 54701cb0ef41Sopenharmony_ci Ld(cp, MemOperand(t8)); 54711cb0ef41Sopenharmony_ci 54721cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 54731cb0ef41Sopenharmony_ci UseScratchRegisterScope temp(this); 54741cb0ef41Sopenharmony_ci Register scratch = temp.Acquire(); 54751cb0ef41Sopenharmony_ci li(scratch, Operand(Context::kInvalidContext)); 54761cb0ef41Sopenharmony_ci Sd(scratch, MemOperand(t8)); 54771cb0ef41Sopenharmony_ci } 54781cb0ef41Sopenharmony_ci 54791cb0ef41Sopenharmony_ci // Pop the arguments, restore registers, and return. 54801cb0ef41Sopenharmony_ci mov(sp, fp); // Respect ABI stack constraint. 54811cb0ef41Sopenharmony_ci Ld(fp, MemOperand(sp, ExitFrameConstants::kCallerFPOffset)); 54821cb0ef41Sopenharmony_ci Ld(ra, MemOperand(sp, ExitFrameConstants::kCallerPCOffset)); 54831cb0ef41Sopenharmony_ci 54841cb0ef41Sopenharmony_ci if (argument_count.is_valid()) { 54851cb0ef41Sopenharmony_ci if (argument_count_is_length) { 54861cb0ef41Sopenharmony_ci daddu(sp, sp, argument_count); 54871cb0ef41Sopenharmony_ci } else { 54881cb0ef41Sopenharmony_ci Dlsa(sp, sp, argument_count, kPointerSizeLog2, t8); 54891cb0ef41Sopenharmony_ci } 54901cb0ef41Sopenharmony_ci } 54911cb0ef41Sopenharmony_ci 54921cb0ef41Sopenharmony_ci if (do_return) { 54931cb0ef41Sopenharmony_ci Ret(USE_DELAY_SLOT); 54941cb0ef41Sopenharmony_ci // If returning, the instruction in the delay slot will be the addiu below. 54951cb0ef41Sopenharmony_ci } 54961cb0ef41Sopenharmony_ci daddiu(sp, sp, 2 * kPointerSize); 54971cb0ef41Sopenharmony_ci} 54981cb0ef41Sopenharmony_ci 54991cb0ef41Sopenharmony_ciint TurboAssembler::ActivationFrameAlignment() { 55001cb0ef41Sopenharmony_ci#if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64 55011cb0ef41Sopenharmony_ci // Running on the real platform. Use the alignment as mandated by the local 55021cb0ef41Sopenharmony_ci // environment. 55031cb0ef41Sopenharmony_ci // Note: This will break if we ever start generating snapshots on one Mips 55041cb0ef41Sopenharmony_ci // platform for another Mips platform with a different alignment. 55051cb0ef41Sopenharmony_ci return base::OS::ActivationFrameAlignment(); 55061cb0ef41Sopenharmony_ci#else // V8_HOST_ARCH_MIPS 55071cb0ef41Sopenharmony_ci // If we are using the simulator then we should always align to the expected 55081cb0ef41Sopenharmony_ci // alignment. As the simulator is used to generate snapshots we do not know 55091cb0ef41Sopenharmony_ci // if the target platform will need alignment, so this is controlled from a 55101cb0ef41Sopenharmony_ci // flag. 55111cb0ef41Sopenharmony_ci return FLAG_sim_stack_alignment; 55121cb0ef41Sopenharmony_ci#endif // V8_HOST_ARCH_MIPS 55131cb0ef41Sopenharmony_ci} 55141cb0ef41Sopenharmony_ci 55151cb0ef41Sopenharmony_civoid MacroAssembler::AssertStackIsAligned() { 55161cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 55171cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 55181cb0ef41Sopenharmony_ci const int frame_alignment = ActivationFrameAlignment(); 55191cb0ef41Sopenharmony_ci const int frame_alignment_mask = frame_alignment - 1; 55201cb0ef41Sopenharmony_ci 55211cb0ef41Sopenharmony_ci if (frame_alignment > kPointerSize) { 55221cb0ef41Sopenharmony_ci Label alignment_as_expected; 55231cb0ef41Sopenharmony_ci DCHECK(base::bits::IsPowerOfTwo(frame_alignment)); 55241cb0ef41Sopenharmony_ci { 55251cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 55261cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 55271cb0ef41Sopenharmony_ci andi(scratch, sp, frame_alignment_mask); 55281cb0ef41Sopenharmony_ci Branch(&alignment_as_expected, eq, scratch, Operand(zero_reg)); 55291cb0ef41Sopenharmony_ci } 55301cb0ef41Sopenharmony_ci // Don't use Check here, as it will call Runtime_Abort re-entering here. 55311cb0ef41Sopenharmony_ci stop(); 55321cb0ef41Sopenharmony_ci bind(&alignment_as_expected); 55331cb0ef41Sopenharmony_ci } 55341cb0ef41Sopenharmony_ci } 55351cb0ef41Sopenharmony_ci} 55361cb0ef41Sopenharmony_ci 55371cb0ef41Sopenharmony_civoid TurboAssembler::SmiUntag(Register dst, const MemOperand& src) { 55381cb0ef41Sopenharmony_ci if (SmiValuesAre32Bits()) { 55391cb0ef41Sopenharmony_ci Lw(dst, MemOperand(src.rm(), SmiWordOffset(src.offset()))); 55401cb0ef41Sopenharmony_ci } else { 55411cb0ef41Sopenharmony_ci DCHECK(SmiValuesAre31Bits()); 55421cb0ef41Sopenharmony_ci Lw(dst, src); 55431cb0ef41Sopenharmony_ci SmiUntag(dst); 55441cb0ef41Sopenharmony_ci } 55451cb0ef41Sopenharmony_ci} 55461cb0ef41Sopenharmony_ci 55471cb0ef41Sopenharmony_civoid TurboAssembler::JumpIfSmi(Register value, Label* smi_label, 55481cb0ef41Sopenharmony_ci BranchDelaySlot bd) { 55491cb0ef41Sopenharmony_ci DCHECK_EQ(0, kSmiTag); 55501cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 55511cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 55521cb0ef41Sopenharmony_ci andi(scratch, value, kSmiTagMask); 55531cb0ef41Sopenharmony_ci Branch(bd, smi_label, eq, scratch, Operand(zero_reg)); 55541cb0ef41Sopenharmony_ci} 55551cb0ef41Sopenharmony_ci 55561cb0ef41Sopenharmony_civoid MacroAssembler::JumpIfNotSmi(Register value, Label* not_smi_label, 55571cb0ef41Sopenharmony_ci BranchDelaySlot bd) { 55581cb0ef41Sopenharmony_ci DCHECK_EQ(0, kSmiTag); 55591cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 55601cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 55611cb0ef41Sopenharmony_ci andi(scratch, value, kSmiTagMask); 55621cb0ef41Sopenharmony_ci Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg)); 55631cb0ef41Sopenharmony_ci} 55641cb0ef41Sopenharmony_ci 55651cb0ef41Sopenharmony_civoid TurboAssembler::AssertNotSmi(Register object) { 55661cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 55671cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 55681cb0ef41Sopenharmony_ci STATIC_ASSERT(kSmiTag == 0); 55691cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 55701cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 55711cb0ef41Sopenharmony_ci andi(scratch, object, kSmiTagMask); 55721cb0ef41Sopenharmony_ci Check(ne, AbortReason::kOperandIsASmi, scratch, Operand(zero_reg)); 55731cb0ef41Sopenharmony_ci } 55741cb0ef41Sopenharmony_ci} 55751cb0ef41Sopenharmony_ci 55761cb0ef41Sopenharmony_civoid TurboAssembler::AssertSmi(Register object) { 55771cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 55781cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 55791cb0ef41Sopenharmony_ci STATIC_ASSERT(kSmiTag == 0); 55801cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 55811cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 55821cb0ef41Sopenharmony_ci andi(scratch, object, kSmiTagMask); 55831cb0ef41Sopenharmony_ci Check(eq, AbortReason::kOperandIsASmi, scratch, Operand(zero_reg)); 55841cb0ef41Sopenharmony_ci } 55851cb0ef41Sopenharmony_ci} 55861cb0ef41Sopenharmony_ci 55871cb0ef41Sopenharmony_civoid MacroAssembler::AssertConstructor(Register object) { 55881cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 55891cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 55901cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 55911cb0ef41Sopenharmony_ci STATIC_ASSERT(kSmiTag == 0); 55921cb0ef41Sopenharmony_ci SmiTst(object, t8); 55931cb0ef41Sopenharmony_ci Check(ne, AbortReason::kOperandIsASmiAndNotAConstructor, t8, 55941cb0ef41Sopenharmony_ci Operand(zero_reg)); 55951cb0ef41Sopenharmony_ci 55961cb0ef41Sopenharmony_ci LoadMap(t8, object); 55971cb0ef41Sopenharmony_ci Lbu(t8, FieldMemOperand(t8, Map::kBitFieldOffset)); 55981cb0ef41Sopenharmony_ci And(t8, t8, Operand(Map::Bits1::IsConstructorBit::kMask)); 55991cb0ef41Sopenharmony_ci Check(ne, AbortReason::kOperandIsNotAConstructor, t8, Operand(zero_reg)); 56001cb0ef41Sopenharmony_ci } 56011cb0ef41Sopenharmony_ci} 56021cb0ef41Sopenharmony_ci 56031cb0ef41Sopenharmony_civoid MacroAssembler::AssertFunction(Register object) { 56041cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 56051cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 56061cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 56071cb0ef41Sopenharmony_ci STATIC_ASSERT(kSmiTag == 0); 56081cb0ef41Sopenharmony_ci SmiTst(object, t8); 56091cb0ef41Sopenharmony_ci Check(ne, AbortReason::kOperandIsASmiAndNotAFunction, t8, 56101cb0ef41Sopenharmony_ci Operand(zero_reg)); 56111cb0ef41Sopenharmony_ci push(object); 56121cb0ef41Sopenharmony_ci LoadMap(object, object); 56131cb0ef41Sopenharmony_ci GetInstanceTypeRange(object, object, FIRST_JS_FUNCTION_TYPE, t8); 56141cb0ef41Sopenharmony_ci Check(ls, AbortReason::kOperandIsNotAFunction, t8, 56151cb0ef41Sopenharmony_ci Operand(LAST_JS_FUNCTION_TYPE - FIRST_JS_FUNCTION_TYPE)); 56161cb0ef41Sopenharmony_ci pop(object); 56171cb0ef41Sopenharmony_ci } 56181cb0ef41Sopenharmony_ci} 56191cb0ef41Sopenharmony_ci 56201cb0ef41Sopenharmony_civoid MacroAssembler::AssertCallableFunction(Register object) { 56211cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 56221cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 56231cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 56241cb0ef41Sopenharmony_ci STATIC_ASSERT(kSmiTag == 0); 56251cb0ef41Sopenharmony_ci SmiTst(object, t8); 56261cb0ef41Sopenharmony_ci Check(ne, AbortReason::kOperandIsASmiAndNotAFunction, t8, 56271cb0ef41Sopenharmony_ci Operand(zero_reg)); 56281cb0ef41Sopenharmony_ci push(object); 56291cb0ef41Sopenharmony_ci LoadMap(object, object); 56301cb0ef41Sopenharmony_ci GetInstanceTypeRange(object, object, FIRST_CALLABLE_JS_FUNCTION_TYPE, t8); 56311cb0ef41Sopenharmony_ci Check(ls, AbortReason::kOperandIsNotACallableFunction, t8, 56321cb0ef41Sopenharmony_ci Operand(LAST_CALLABLE_JS_FUNCTION_TYPE - 56331cb0ef41Sopenharmony_ci FIRST_CALLABLE_JS_FUNCTION_TYPE)); 56341cb0ef41Sopenharmony_ci pop(object); 56351cb0ef41Sopenharmony_ci } 56361cb0ef41Sopenharmony_ci} 56371cb0ef41Sopenharmony_ci 56381cb0ef41Sopenharmony_civoid MacroAssembler::AssertBoundFunction(Register object) { 56391cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 56401cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 56411cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 56421cb0ef41Sopenharmony_ci STATIC_ASSERT(kSmiTag == 0); 56431cb0ef41Sopenharmony_ci SmiTst(object, t8); 56441cb0ef41Sopenharmony_ci Check(ne, AbortReason::kOperandIsASmiAndNotABoundFunction, t8, 56451cb0ef41Sopenharmony_ci Operand(zero_reg)); 56461cb0ef41Sopenharmony_ci GetObjectType(object, t8, t8); 56471cb0ef41Sopenharmony_ci Check(eq, AbortReason::kOperandIsNotABoundFunction, t8, 56481cb0ef41Sopenharmony_ci Operand(JS_BOUND_FUNCTION_TYPE)); 56491cb0ef41Sopenharmony_ci } 56501cb0ef41Sopenharmony_ci} 56511cb0ef41Sopenharmony_ci 56521cb0ef41Sopenharmony_civoid MacroAssembler::AssertGeneratorObject(Register object) { 56531cb0ef41Sopenharmony_ci if (!FLAG_debug_code) return; 56541cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 56551cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 56561cb0ef41Sopenharmony_ci STATIC_ASSERT(kSmiTag == 0); 56571cb0ef41Sopenharmony_ci SmiTst(object, t8); 56581cb0ef41Sopenharmony_ci Check(ne, AbortReason::kOperandIsASmiAndNotAGeneratorObject, t8, 56591cb0ef41Sopenharmony_ci Operand(zero_reg)); 56601cb0ef41Sopenharmony_ci 56611cb0ef41Sopenharmony_ci GetObjectType(object, t8, t8); 56621cb0ef41Sopenharmony_ci 56631cb0ef41Sopenharmony_ci Label done; 56641cb0ef41Sopenharmony_ci 56651cb0ef41Sopenharmony_ci // Check if JSGeneratorObject 56661cb0ef41Sopenharmony_ci Branch(&done, eq, t8, Operand(JS_GENERATOR_OBJECT_TYPE)); 56671cb0ef41Sopenharmony_ci 56681cb0ef41Sopenharmony_ci // Check if JSAsyncFunctionObject (See MacroAssembler::CompareInstanceType) 56691cb0ef41Sopenharmony_ci Branch(&done, eq, t8, Operand(JS_ASYNC_FUNCTION_OBJECT_TYPE)); 56701cb0ef41Sopenharmony_ci 56711cb0ef41Sopenharmony_ci // Check if JSAsyncGeneratorObject 56721cb0ef41Sopenharmony_ci Branch(&done, eq, t8, Operand(JS_ASYNC_GENERATOR_OBJECT_TYPE)); 56731cb0ef41Sopenharmony_ci 56741cb0ef41Sopenharmony_ci Abort(AbortReason::kOperandIsNotAGeneratorObject); 56751cb0ef41Sopenharmony_ci 56761cb0ef41Sopenharmony_ci bind(&done); 56771cb0ef41Sopenharmony_ci} 56781cb0ef41Sopenharmony_ci 56791cb0ef41Sopenharmony_civoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object, 56801cb0ef41Sopenharmony_ci Register scratch) { 56811cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 56821cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 56831cb0ef41Sopenharmony_ci Label done_checking; 56841cb0ef41Sopenharmony_ci AssertNotSmi(object); 56851cb0ef41Sopenharmony_ci LoadRoot(scratch, RootIndex::kUndefinedValue); 56861cb0ef41Sopenharmony_ci Branch(&done_checking, eq, object, Operand(scratch)); 56871cb0ef41Sopenharmony_ci GetObjectType(object, scratch, scratch); 56881cb0ef41Sopenharmony_ci Assert(eq, AbortReason::kExpectedUndefinedOrCell, scratch, 56891cb0ef41Sopenharmony_ci Operand(ALLOCATION_SITE_TYPE)); 56901cb0ef41Sopenharmony_ci bind(&done_checking); 56911cb0ef41Sopenharmony_ci } 56921cb0ef41Sopenharmony_ci} 56931cb0ef41Sopenharmony_ci 56941cb0ef41Sopenharmony_civoid TurboAssembler::Float32Max(FPURegister dst, FPURegister src1, 56951cb0ef41Sopenharmony_ci FPURegister src2, Label* out_of_line) { 56961cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 56971cb0ef41Sopenharmony_ci if (src1 == src2) { 56981cb0ef41Sopenharmony_ci Move_s(dst, src1); 56991cb0ef41Sopenharmony_ci return; 57001cb0ef41Sopenharmony_ci } 57011cb0ef41Sopenharmony_ci 57021cb0ef41Sopenharmony_ci // Check if one of operands is NaN. 57031cb0ef41Sopenharmony_ci CompareIsNanF32(src1, src2); 57041cb0ef41Sopenharmony_ci BranchTrueF(out_of_line); 57051cb0ef41Sopenharmony_ci 57061cb0ef41Sopenharmony_ci if (kArchVariant >= kMips64r6) { 57071cb0ef41Sopenharmony_ci max_s(dst, src1, src2); 57081cb0ef41Sopenharmony_ci } else { 57091cb0ef41Sopenharmony_ci Label return_left, return_right, done; 57101cb0ef41Sopenharmony_ci 57111cb0ef41Sopenharmony_ci CompareF32(OLT, src1, src2); 57121cb0ef41Sopenharmony_ci BranchTrueShortF(&return_right); 57131cb0ef41Sopenharmony_ci CompareF32(OLT, src2, src1); 57141cb0ef41Sopenharmony_ci BranchTrueShortF(&return_left); 57151cb0ef41Sopenharmony_ci 57161cb0ef41Sopenharmony_ci // Operands are equal, but check for +/-0. 57171cb0ef41Sopenharmony_ci { 57181cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 57191cb0ef41Sopenharmony_ci mfc1(t8, src1); 57201cb0ef41Sopenharmony_ci dsll32(t8, t8, 0); 57211cb0ef41Sopenharmony_ci Branch(&return_left, eq, t8, Operand(zero_reg)); 57221cb0ef41Sopenharmony_ci Branch(&return_right); 57231cb0ef41Sopenharmony_ci } 57241cb0ef41Sopenharmony_ci 57251cb0ef41Sopenharmony_ci bind(&return_right); 57261cb0ef41Sopenharmony_ci if (src2 != dst) { 57271cb0ef41Sopenharmony_ci Move_s(dst, src2); 57281cb0ef41Sopenharmony_ci } 57291cb0ef41Sopenharmony_ci Branch(&done); 57301cb0ef41Sopenharmony_ci 57311cb0ef41Sopenharmony_ci bind(&return_left); 57321cb0ef41Sopenharmony_ci if (src1 != dst) { 57331cb0ef41Sopenharmony_ci Move_s(dst, src1); 57341cb0ef41Sopenharmony_ci } 57351cb0ef41Sopenharmony_ci 57361cb0ef41Sopenharmony_ci bind(&done); 57371cb0ef41Sopenharmony_ci } 57381cb0ef41Sopenharmony_ci} 57391cb0ef41Sopenharmony_ci 57401cb0ef41Sopenharmony_civoid TurboAssembler::Float32MaxOutOfLine(FPURegister dst, FPURegister src1, 57411cb0ef41Sopenharmony_ci FPURegister src2) { 57421cb0ef41Sopenharmony_ci add_s(dst, src1, src2); 57431cb0ef41Sopenharmony_ci} 57441cb0ef41Sopenharmony_ci 57451cb0ef41Sopenharmony_civoid TurboAssembler::Float32Min(FPURegister dst, FPURegister src1, 57461cb0ef41Sopenharmony_ci FPURegister src2, Label* out_of_line) { 57471cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 57481cb0ef41Sopenharmony_ci if (src1 == src2) { 57491cb0ef41Sopenharmony_ci Move_s(dst, src1); 57501cb0ef41Sopenharmony_ci return; 57511cb0ef41Sopenharmony_ci } 57521cb0ef41Sopenharmony_ci 57531cb0ef41Sopenharmony_ci // Check if one of operands is NaN. 57541cb0ef41Sopenharmony_ci CompareIsNanF32(src1, src2); 57551cb0ef41Sopenharmony_ci BranchTrueF(out_of_line); 57561cb0ef41Sopenharmony_ci 57571cb0ef41Sopenharmony_ci if (kArchVariant >= kMips64r6) { 57581cb0ef41Sopenharmony_ci min_s(dst, src1, src2); 57591cb0ef41Sopenharmony_ci } else { 57601cb0ef41Sopenharmony_ci Label return_left, return_right, done; 57611cb0ef41Sopenharmony_ci 57621cb0ef41Sopenharmony_ci CompareF32(OLT, src1, src2); 57631cb0ef41Sopenharmony_ci BranchTrueShortF(&return_left); 57641cb0ef41Sopenharmony_ci CompareF32(OLT, src2, src1); 57651cb0ef41Sopenharmony_ci BranchTrueShortF(&return_right); 57661cb0ef41Sopenharmony_ci 57671cb0ef41Sopenharmony_ci // Left equals right => check for -0. 57681cb0ef41Sopenharmony_ci { 57691cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 57701cb0ef41Sopenharmony_ci mfc1(t8, src1); 57711cb0ef41Sopenharmony_ci dsll32(t8, t8, 0); 57721cb0ef41Sopenharmony_ci Branch(&return_right, eq, t8, Operand(zero_reg)); 57731cb0ef41Sopenharmony_ci Branch(&return_left); 57741cb0ef41Sopenharmony_ci } 57751cb0ef41Sopenharmony_ci 57761cb0ef41Sopenharmony_ci bind(&return_right); 57771cb0ef41Sopenharmony_ci if (src2 != dst) { 57781cb0ef41Sopenharmony_ci Move_s(dst, src2); 57791cb0ef41Sopenharmony_ci } 57801cb0ef41Sopenharmony_ci Branch(&done); 57811cb0ef41Sopenharmony_ci 57821cb0ef41Sopenharmony_ci bind(&return_left); 57831cb0ef41Sopenharmony_ci if (src1 != dst) { 57841cb0ef41Sopenharmony_ci Move_s(dst, src1); 57851cb0ef41Sopenharmony_ci } 57861cb0ef41Sopenharmony_ci 57871cb0ef41Sopenharmony_ci bind(&done); 57881cb0ef41Sopenharmony_ci } 57891cb0ef41Sopenharmony_ci} 57901cb0ef41Sopenharmony_ci 57911cb0ef41Sopenharmony_civoid TurboAssembler::Float32MinOutOfLine(FPURegister dst, FPURegister src1, 57921cb0ef41Sopenharmony_ci FPURegister src2) { 57931cb0ef41Sopenharmony_ci add_s(dst, src1, src2); 57941cb0ef41Sopenharmony_ci} 57951cb0ef41Sopenharmony_ci 57961cb0ef41Sopenharmony_civoid TurboAssembler::Float64Max(FPURegister dst, FPURegister src1, 57971cb0ef41Sopenharmony_ci FPURegister src2, Label* out_of_line) { 57981cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 57991cb0ef41Sopenharmony_ci if (src1 == src2) { 58001cb0ef41Sopenharmony_ci Move_d(dst, src1); 58011cb0ef41Sopenharmony_ci return; 58021cb0ef41Sopenharmony_ci } 58031cb0ef41Sopenharmony_ci 58041cb0ef41Sopenharmony_ci // Check if one of operands is NaN. 58051cb0ef41Sopenharmony_ci CompareIsNanF64(src1, src2); 58061cb0ef41Sopenharmony_ci BranchTrueF(out_of_line); 58071cb0ef41Sopenharmony_ci 58081cb0ef41Sopenharmony_ci if (kArchVariant >= kMips64r6) { 58091cb0ef41Sopenharmony_ci max_d(dst, src1, src2); 58101cb0ef41Sopenharmony_ci } else { 58111cb0ef41Sopenharmony_ci Label return_left, return_right, done; 58121cb0ef41Sopenharmony_ci 58131cb0ef41Sopenharmony_ci CompareF64(OLT, src1, src2); 58141cb0ef41Sopenharmony_ci BranchTrueShortF(&return_right); 58151cb0ef41Sopenharmony_ci CompareF64(OLT, src2, src1); 58161cb0ef41Sopenharmony_ci BranchTrueShortF(&return_left); 58171cb0ef41Sopenharmony_ci 58181cb0ef41Sopenharmony_ci // Left equals right => check for -0. 58191cb0ef41Sopenharmony_ci { 58201cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 58211cb0ef41Sopenharmony_ci dmfc1(t8, src1); 58221cb0ef41Sopenharmony_ci Branch(&return_left, eq, t8, Operand(zero_reg)); 58231cb0ef41Sopenharmony_ci Branch(&return_right); 58241cb0ef41Sopenharmony_ci } 58251cb0ef41Sopenharmony_ci 58261cb0ef41Sopenharmony_ci bind(&return_right); 58271cb0ef41Sopenharmony_ci if (src2 != dst) { 58281cb0ef41Sopenharmony_ci Move_d(dst, src2); 58291cb0ef41Sopenharmony_ci } 58301cb0ef41Sopenharmony_ci Branch(&done); 58311cb0ef41Sopenharmony_ci 58321cb0ef41Sopenharmony_ci bind(&return_left); 58331cb0ef41Sopenharmony_ci if (src1 != dst) { 58341cb0ef41Sopenharmony_ci Move_d(dst, src1); 58351cb0ef41Sopenharmony_ci } 58361cb0ef41Sopenharmony_ci 58371cb0ef41Sopenharmony_ci bind(&done); 58381cb0ef41Sopenharmony_ci } 58391cb0ef41Sopenharmony_ci} 58401cb0ef41Sopenharmony_ci 58411cb0ef41Sopenharmony_civoid TurboAssembler::Float64MaxOutOfLine(FPURegister dst, FPURegister src1, 58421cb0ef41Sopenharmony_ci FPURegister src2) { 58431cb0ef41Sopenharmony_ci add_d(dst, src1, src2); 58441cb0ef41Sopenharmony_ci} 58451cb0ef41Sopenharmony_ci 58461cb0ef41Sopenharmony_civoid TurboAssembler::Float64Min(FPURegister dst, FPURegister src1, 58471cb0ef41Sopenharmony_ci FPURegister src2, Label* out_of_line) { 58481cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 58491cb0ef41Sopenharmony_ci if (src1 == src2) { 58501cb0ef41Sopenharmony_ci Move_d(dst, src1); 58511cb0ef41Sopenharmony_ci return; 58521cb0ef41Sopenharmony_ci } 58531cb0ef41Sopenharmony_ci 58541cb0ef41Sopenharmony_ci // Check if one of operands is NaN. 58551cb0ef41Sopenharmony_ci CompareIsNanF64(src1, src2); 58561cb0ef41Sopenharmony_ci BranchTrueF(out_of_line); 58571cb0ef41Sopenharmony_ci 58581cb0ef41Sopenharmony_ci if (kArchVariant >= kMips64r6) { 58591cb0ef41Sopenharmony_ci min_d(dst, src1, src2); 58601cb0ef41Sopenharmony_ci } else { 58611cb0ef41Sopenharmony_ci Label return_left, return_right, done; 58621cb0ef41Sopenharmony_ci 58631cb0ef41Sopenharmony_ci CompareF64(OLT, src1, src2); 58641cb0ef41Sopenharmony_ci BranchTrueShortF(&return_left); 58651cb0ef41Sopenharmony_ci CompareF64(OLT, src2, src1); 58661cb0ef41Sopenharmony_ci BranchTrueShortF(&return_right); 58671cb0ef41Sopenharmony_ci 58681cb0ef41Sopenharmony_ci // Left equals right => check for -0. 58691cb0ef41Sopenharmony_ci { 58701cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 58711cb0ef41Sopenharmony_ci dmfc1(t8, src1); 58721cb0ef41Sopenharmony_ci Branch(&return_right, eq, t8, Operand(zero_reg)); 58731cb0ef41Sopenharmony_ci Branch(&return_left); 58741cb0ef41Sopenharmony_ci } 58751cb0ef41Sopenharmony_ci 58761cb0ef41Sopenharmony_ci bind(&return_right); 58771cb0ef41Sopenharmony_ci if (src2 != dst) { 58781cb0ef41Sopenharmony_ci Move_d(dst, src2); 58791cb0ef41Sopenharmony_ci } 58801cb0ef41Sopenharmony_ci Branch(&done); 58811cb0ef41Sopenharmony_ci 58821cb0ef41Sopenharmony_ci bind(&return_left); 58831cb0ef41Sopenharmony_ci if (src1 != dst) { 58841cb0ef41Sopenharmony_ci Move_d(dst, src1); 58851cb0ef41Sopenharmony_ci } 58861cb0ef41Sopenharmony_ci 58871cb0ef41Sopenharmony_ci bind(&done); 58881cb0ef41Sopenharmony_ci } 58891cb0ef41Sopenharmony_ci} 58901cb0ef41Sopenharmony_ci 58911cb0ef41Sopenharmony_civoid TurboAssembler::Float64MinOutOfLine(FPURegister dst, FPURegister src1, 58921cb0ef41Sopenharmony_ci FPURegister src2) { 58931cb0ef41Sopenharmony_ci add_d(dst, src1, src2); 58941cb0ef41Sopenharmony_ci} 58951cb0ef41Sopenharmony_ci 58961cb0ef41Sopenharmony_cistatic const int kRegisterPassedArguments = 8; 58971cb0ef41Sopenharmony_ci 58981cb0ef41Sopenharmony_ciint TurboAssembler::CalculateStackPassedWords(int num_reg_arguments, 58991cb0ef41Sopenharmony_ci int num_double_arguments) { 59001cb0ef41Sopenharmony_ci int stack_passed_words = 0; 59011cb0ef41Sopenharmony_ci num_reg_arguments += 2 * num_double_arguments; 59021cb0ef41Sopenharmony_ci 59031cb0ef41Sopenharmony_ci // O32: Up to four simple arguments are passed in registers a0..a3. 59041cb0ef41Sopenharmony_ci // N64: Up to eight simple arguments are passed in registers a0..a7. 59051cb0ef41Sopenharmony_ci if (num_reg_arguments > kRegisterPassedArguments) { 59061cb0ef41Sopenharmony_ci stack_passed_words += num_reg_arguments - kRegisterPassedArguments; 59071cb0ef41Sopenharmony_ci } 59081cb0ef41Sopenharmony_ci stack_passed_words += kCArgSlotCount; 59091cb0ef41Sopenharmony_ci return stack_passed_words; 59101cb0ef41Sopenharmony_ci} 59111cb0ef41Sopenharmony_ci 59121cb0ef41Sopenharmony_civoid TurboAssembler::PrepareCallCFunction(int num_reg_arguments, 59131cb0ef41Sopenharmony_ci int num_double_arguments, 59141cb0ef41Sopenharmony_ci Register scratch) { 59151cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 59161cb0ef41Sopenharmony_ci int frame_alignment = ActivationFrameAlignment(); 59171cb0ef41Sopenharmony_ci 59181cb0ef41Sopenharmony_ci // n64: Up to eight simple arguments in a0..a3, a4..a7, No argument slots. 59191cb0ef41Sopenharmony_ci // O32: Up to four simple arguments are passed in registers a0..a3. 59201cb0ef41Sopenharmony_ci // Those four arguments must have reserved argument slots on the stack for 59211cb0ef41Sopenharmony_ci // mips, even though those argument slots are not normally used. 59221cb0ef41Sopenharmony_ci // Both ABIs: Remaining arguments are pushed on the stack, above (higher 59231cb0ef41Sopenharmony_ci // address than) the (O32) argument slots. (arg slot calculation handled by 59241cb0ef41Sopenharmony_ci // CalculateStackPassedWords()). 59251cb0ef41Sopenharmony_ci int stack_passed_arguments = 59261cb0ef41Sopenharmony_ci CalculateStackPassedWords(num_reg_arguments, num_double_arguments); 59271cb0ef41Sopenharmony_ci if (frame_alignment > kPointerSize) { 59281cb0ef41Sopenharmony_ci // Make stack end at alignment and make room for num_arguments - 4 words 59291cb0ef41Sopenharmony_ci // and the original value of sp. 59301cb0ef41Sopenharmony_ci mov(scratch, sp); 59311cb0ef41Sopenharmony_ci Dsubu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); 59321cb0ef41Sopenharmony_ci DCHECK(base::bits::IsPowerOfTwo(frame_alignment)); 59331cb0ef41Sopenharmony_ci And(sp, sp, Operand(-frame_alignment)); 59341cb0ef41Sopenharmony_ci Sd(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); 59351cb0ef41Sopenharmony_ci } else { 59361cb0ef41Sopenharmony_ci Dsubu(sp, sp, Operand(stack_passed_arguments * kPointerSize)); 59371cb0ef41Sopenharmony_ci } 59381cb0ef41Sopenharmony_ci} 59391cb0ef41Sopenharmony_ci 59401cb0ef41Sopenharmony_civoid TurboAssembler::PrepareCallCFunction(int num_reg_arguments, 59411cb0ef41Sopenharmony_ci Register scratch) { 59421cb0ef41Sopenharmony_ci PrepareCallCFunction(num_reg_arguments, 0, scratch); 59431cb0ef41Sopenharmony_ci} 59441cb0ef41Sopenharmony_ci 59451cb0ef41Sopenharmony_civoid TurboAssembler::CallCFunction(ExternalReference function, 59461cb0ef41Sopenharmony_ci int num_reg_arguments, 59471cb0ef41Sopenharmony_ci int num_double_arguments) { 59481cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 59491cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 59501cb0ef41Sopenharmony_ci li(t9, function); 59511cb0ef41Sopenharmony_ci CallCFunctionHelper(t9, num_reg_arguments, num_double_arguments); 59521cb0ef41Sopenharmony_ci} 59531cb0ef41Sopenharmony_ci 59541cb0ef41Sopenharmony_civoid TurboAssembler::CallCFunction(Register function, int num_reg_arguments, 59551cb0ef41Sopenharmony_ci int num_double_arguments) { 59561cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 59571cb0ef41Sopenharmony_ci CallCFunctionHelper(function, num_reg_arguments, num_double_arguments); 59581cb0ef41Sopenharmony_ci} 59591cb0ef41Sopenharmony_ci 59601cb0ef41Sopenharmony_civoid TurboAssembler::CallCFunction(ExternalReference function, 59611cb0ef41Sopenharmony_ci int num_arguments) { 59621cb0ef41Sopenharmony_ci CallCFunction(function, num_arguments, 0); 59631cb0ef41Sopenharmony_ci} 59641cb0ef41Sopenharmony_ci 59651cb0ef41Sopenharmony_civoid TurboAssembler::CallCFunction(Register function, int num_arguments) { 59661cb0ef41Sopenharmony_ci CallCFunction(function, num_arguments, 0); 59671cb0ef41Sopenharmony_ci} 59681cb0ef41Sopenharmony_ci 59691cb0ef41Sopenharmony_civoid TurboAssembler::CallCFunctionHelper(Register function, 59701cb0ef41Sopenharmony_ci int num_reg_arguments, 59711cb0ef41Sopenharmony_ci int num_double_arguments) { 59721cb0ef41Sopenharmony_ci DCHECK_LE(num_reg_arguments + num_double_arguments, kMaxCParameters); 59731cb0ef41Sopenharmony_ci DCHECK(has_frame()); 59741cb0ef41Sopenharmony_ci // Make sure that the stack is aligned before calling a C function unless 59751cb0ef41Sopenharmony_ci // running in the simulator. The simulator has its own alignment check which 59761cb0ef41Sopenharmony_ci // provides more information. 59771cb0ef41Sopenharmony_ci // The argument stots are presumed to have been set up by 59781cb0ef41Sopenharmony_ci // PrepareCallCFunction. The C function must be called via t9, for mips ABI. 59791cb0ef41Sopenharmony_ci 59801cb0ef41Sopenharmony_ci#if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64 59811cb0ef41Sopenharmony_ci if (FLAG_debug_code) { 59821cb0ef41Sopenharmony_ci int frame_alignment = base::OS::ActivationFrameAlignment(); 59831cb0ef41Sopenharmony_ci int frame_alignment_mask = frame_alignment - 1; 59841cb0ef41Sopenharmony_ci if (frame_alignment > kPointerSize) { 59851cb0ef41Sopenharmony_ci DCHECK(base::bits::IsPowerOfTwo(frame_alignment)); 59861cb0ef41Sopenharmony_ci Label alignment_as_expected; 59871cb0ef41Sopenharmony_ci { 59881cb0ef41Sopenharmony_ci UseScratchRegisterScope temps(this); 59891cb0ef41Sopenharmony_ci Register scratch = temps.Acquire(); 59901cb0ef41Sopenharmony_ci And(scratch, sp, Operand(frame_alignment_mask)); 59911cb0ef41Sopenharmony_ci Branch(&alignment_as_expected, eq, scratch, Operand(zero_reg)); 59921cb0ef41Sopenharmony_ci } 59931cb0ef41Sopenharmony_ci // Don't use Check here, as it will call Runtime_Abort possibly 59941cb0ef41Sopenharmony_ci // re-entering here. 59951cb0ef41Sopenharmony_ci stop(); 59961cb0ef41Sopenharmony_ci bind(&alignment_as_expected); 59971cb0ef41Sopenharmony_ci } 59981cb0ef41Sopenharmony_ci } 59991cb0ef41Sopenharmony_ci#endif // V8_HOST_ARCH_MIPS 60001cb0ef41Sopenharmony_ci 60011cb0ef41Sopenharmony_ci // Just call directly. The function called cannot cause a GC, or 60021cb0ef41Sopenharmony_ci // allow preemption, so the return address in the link register 60031cb0ef41Sopenharmony_ci // stays correct. 60041cb0ef41Sopenharmony_ci { 60051cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 60061cb0ef41Sopenharmony_ci if (function != t9) { 60071cb0ef41Sopenharmony_ci mov(t9, function); 60081cb0ef41Sopenharmony_ci function = t9; 60091cb0ef41Sopenharmony_ci } 60101cb0ef41Sopenharmony_ci 60111cb0ef41Sopenharmony_ci // Save the frame pointer and PC so that the stack layout remains iterable, 60121cb0ef41Sopenharmony_ci // even without an ExitFrame which normally exists between JS and C frames. 60131cb0ef41Sopenharmony_ci // 't' registers are caller-saved so this is safe as a scratch register. 60141cb0ef41Sopenharmony_ci Register pc_scratch = t1; 60151cb0ef41Sopenharmony_ci Register scratch = t2; 60161cb0ef41Sopenharmony_ci DCHECK(!AreAliased(pc_scratch, scratch, function)); 60171cb0ef41Sopenharmony_ci 60181cb0ef41Sopenharmony_ci mov(scratch, ra); 60191cb0ef41Sopenharmony_ci nal(); 60201cb0ef41Sopenharmony_ci mov(pc_scratch, ra); 60211cb0ef41Sopenharmony_ci mov(ra, scratch); 60221cb0ef41Sopenharmony_ci 60231cb0ef41Sopenharmony_ci // See x64 code for reasoning about how to address the isolate data fields. 60241cb0ef41Sopenharmony_ci if (root_array_available()) { 60251cb0ef41Sopenharmony_ci Sd(pc_scratch, MemOperand(kRootRegister, 60261cb0ef41Sopenharmony_ci IsolateData::fast_c_call_caller_pc_offset())); 60271cb0ef41Sopenharmony_ci Sd(fp, MemOperand(kRootRegister, 60281cb0ef41Sopenharmony_ci IsolateData::fast_c_call_caller_fp_offset())); 60291cb0ef41Sopenharmony_ci } else { 60301cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(isolate()); 60311cb0ef41Sopenharmony_ci li(scratch, ExternalReference::fast_c_call_caller_pc_address(isolate())); 60321cb0ef41Sopenharmony_ci Sd(pc_scratch, MemOperand(scratch)); 60331cb0ef41Sopenharmony_ci li(scratch, ExternalReference::fast_c_call_caller_fp_address(isolate())); 60341cb0ef41Sopenharmony_ci Sd(fp, MemOperand(scratch)); 60351cb0ef41Sopenharmony_ci } 60361cb0ef41Sopenharmony_ci 60371cb0ef41Sopenharmony_ci Call(function); 60381cb0ef41Sopenharmony_ci 60391cb0ef41Sopenharmony_ci // We don't unset the PC; the FP is the source of truth. 60401cb0ef41Sopenharmony_ci if (root_array_available()) { 60411cb0ef41Sopenharmony_ci Sd(zero_reg, MemOperand(kRootRegister, 60421cb0ef41Sopenharmony_ci IsolateData::fast_c_call_caller_fp_offset())); 60431cb0ef41Sopenharmony_ci } else { 60441cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(isolate()); 60451cb0ef41Sopenharmony_ci li(scratch, ExternalReference::fast_c_call_caller_fp_address(isolate())); 60461cb0ef41Sopenharmony_ci Sd(zero_reg, MemOperand(scratch)); 60471cb0ef41Sopenharmony_ci } 60481cb0ef41Sopenharmony_ci 60491cb0ef41Sopenharmony_ci int stack_passed_arguments = 60501cb0ef41Sopenharmony_ci CalculateStackPassedWords(num_reg_arguments, num_double_arguments); 60511cb0ef41Sopenharmony_ci 60521cb0ef41Sopenharmony_ci if (base::OS::ActivationFrameAlignment() > kPointerSize) { 60531cb0ef41Sopenharmony_ci Ld(sp, MemOperand(sp, stack_passed_arguments * kPointerSize)); 60541cb0ef41Sopenharmony_ci } else { 60551cb0ef41Sopenharmony_ci Daddu(sp, sp, Operand(stack_passed_arguments * kPointerSize)); 60561cb0ef41Sopenharmony_ci } 60571cb0ef41Sopenharmony_ci 60581cb0ef41Sopenharmony_ci set_pc_for_safepoint(); 60591cb0ef41Sopenharmony_ci } 60601cb0ef41Sopenharmony_ci} 60611cb0ef41Sopenharmony_ci 60621cb0ef41Sopenharmony_ci#undef BRANCH_ARGS_CHECK 60631cb0ef41Sopenharmony_ci 60641cb0ef41Sopenharmony_civoid TurboAssembler::CheckPageFlag(Register object, Register scratch, int mask, 60651cb0ef41Sopenharmony_ci Condition cc, Label* condition_met) { 60661cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 60671cb0ef41Sopenharmony_ci And(scratch, object, Operand(~kPageAlignmentMask)); 60681cb0ef41Sopenharmony_ci Ld(scratch, MemOperand(scratch, BasicMemoryChunk::kFlagsOffset)); 60691cb0ef41Sopenharmony_ci And(scratch, scratch, Operand(mask)); 60701cb0ef41Sopenharmony_ci Branch(condition_met, cc, scratch, Operand(zero_reg)); 60711cb0ef41Sopenharmony_ci} 60721cb0ef41Sopenharmony_ci 60731cb0ef41Sopenharmony_ciRegister GetRegisterThatIsNotOneOf(Register reg1, Register reg2, Register reg3, 60741cb0ef41Sopenharmony_ci Register reg4, Register reg5, 60751cb0ef41Sopenharmony_ci Register reg6) { 60761cb0ef41Sopenharmony_ci RegList regs = {reg1, reg2, reg3, reg4, reg5, reg6}; 60771cb0ef41Sopenharmony_ci 60781cb0ef41Sopenharmony_ci const RegisterConfiguration* config = RegisterConfiguration::Default(); 60791cb0ef41Sopenharmony_ci for (int i = 0; i < config->num_allocatable_general_registers(); ++i) { 60801cb0ef41Sopenharmony_ci int code = config->GetAllocatableGeneralCode(i); 60811cb0ef41Sopenharmony_ci Register candidate = Register::from_code(code); 60821cb0ef41Sopenharmony_ci if (regs.has(candidate)) continue; 60831cb0ef41Sopenharmony_ci return candidate; 60841cb0ef41Sopenharmony_ci } 60851cb0ef41Sopenharmony_ci UNREACHABLE(); 60861cb0ef41Sopenharmony_ci} 60871cb0ef41Sopenharmony_ci 60881cb0ef41Sopenharmony_civoid TurboAssembler::ComputeCodeStartAddress(Register dst) { 60891cb0ef41Sopenharmony_ci // This push on ra and the pop below together ensure that we restore the 60901cb0ef41Sopenharmony_ci // register ra, which is needed while computing the code start address. 60911cb0ef41Sopenharmony_ci push(ra); 60921cb0ef41Sopenharmony_ci 60931cb0ef41Sopenharmony_ci // The nal instruction puts the address of the current instruction into 60941cb0ef41Sopenharmony_ci // the return address (ra) register, which we can use later on. 60951cb0ef41Sopenharmony_ci if (kArchVariant == kMips64r6) { 60961cb0ef41Sopenharmony_ci addiupc(ra, 1); 60971cb0ef41Sopenharmony_ci } else { 60981cb0ef41Sopenharmony_ci nal(); 60991cb0ef41Sopenharmony_ci nop(); 61001cb0ef41Sopenharmony_ci } 61011cb0ef41Sopenharmony_ci int pc = pc_offset(); 61021cb0ef41Sopenharmony_ci li(dst, Operand(pc)); 61031cb0ef41Sopenharmony_ci Dsubu(dst, ra, dst); 61041cb0ef41Sopenharmony_ci 61051cb0ef41Sopenharmony_ci pop(ra); // Restore ra 61061cb0ef41Sopenharmony_ci} 61071cb0ef41Sopenharmony_ci 61081cb0ef41Sopenharmony_civoid TurboAssembler::CallForDeoptimization(Builtin target, int, Label* exit, 61091cb0ef41Sopenharmony_ci DeoptimizeKind kind, Label* ret, 61101cb0ef41Sopenharmony_ci Label*) { 61111cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 61121cb0ef41Sopenharmony_ci BlockTrampolinePoolScope block_trampoline_pool(this); 61131cb0ef41Sopenharmony_ci Ld(t9, 61141cb0ef41Sopenharmony_ci MemOperand(kRootRegister, IsolateData::BuiltinEntrySlotOffset(target))); 61151cb0ef41Sopenharmony_ci Call(t9); 61161cb0ef41Sopenharmony_ci DCHECK_EQ(SizeOfCodeGeneratedSince(exit), 61171cb0ef41Sopenharmony_ci (kind == DeoptimizeKind::kLazy) ? Deoptimizer::kLazyDeoptExitSize 61181cb0ef41Sopenharmony_ci : Deoptimizer::kEagerDeoptExitSize); 61191cb0ef41Sopenharmony_ci} 61201cb0ef41Sopenharmony_ci 61211cb0ef41Sopenharmony_civoid TurboAssembler::LoadCodeObjectEntry(Register destination, 61221cb0ef41Sopenharmony_ci Register code_object) { 61231cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 61241cb0ef41Sopenharmony_ci // Code objects are called differently depending on whether we are generating 61251cb0ef41Sopenharmony_ci // builtin code (which will later be embedded into the binary) or compiling 61261cb0ef41Sopenharmony_ci // user JS code at runtime. 61271cb0ef41Sopenharmony_ci // * Builtin code runs in --jitless mode and thus must not call into on-heap 61281cb0ef41Sopenharmony_ci // Code targets. Instead, we dispatch through the builtins entry table. 61291cb0ef41Sopenharmony_ci // * Codegen at runtime does not have this restriction and we can use the 61301cb0ef41Sopenharmony_ci // shorter, branchless instruction sequence. The assumption here is that 61311cb0ef41Sopenharmony_ci // targets are usually generated code and not builtin Code objects. 61321cb0ef41Sopenharmony_ci if (options().isolate_independent_code) { 61331cb0ef41Sopenharmony_ci DCHECK(root_array_available()); 61341cb0ef41Sopenharmony_ci Label if_code_is_off_heap, out; 61351cb0ef41Sopenharmony_ci 61361cb0ef41Sopenharmony_ci Register scratch = kScratchReg; 61371cb0ef41Sopenharmony_ci DCHECK(!AreAliased(destination, scratch)); 61381cb0ef41Sopenharmony_ci DCHECK(!AreAliased(code_object, scratch)); 61391cb0ef41Sopenharmony_ci 61401cb0ef41Sopenharmony_ci // Check whether the Code object is an off-heap trampoline. If so, call its 61411cb0ef41Sopenharmony_ci // (off-heap) entry point directly without going through the (on-heap) 61421cb0ef41Sopenharmony_ci // trampoline. Otherwise, just call the Code object as always. 61431cb0ef41Sopenharmony_ci Lw(scratch, FieldMemOperand(code_object, Code::kFlagsOffset)); 61441cb0ef41Sopenharmony_ci And(scratch, scratch, Operand(Code::IsOffHeapTrampoline::kMask)); 61451cb0ef41Sopenharmony_ci Branch(&if_code_is_off_heap, ne, scratch, Operand(zero_reg)); 61461cb0ef41Sopenharmony_ci 61471cb0ef41Sopenharmony_ci // Not an off-heap trampoline object, the entry point is at 61481cb0ef41Sopenharmony_ci // Code::raw_instruction_start(). 61491cb0ef41Sopenharmony_ci Daddu(destination, code_object, Code::kHeaderSize - kHeapObjectTag); 61501cb0ef41Sopenharmony_ci Branch(&out); 61511cb0ef41Sopenharmony_ci 61521cb0ef41Sopenharmony_ci // An off-heap trampoline, the entry point is loaded from the builtin entry 61531cb0ef41Sopenharmony_ci // table. 61541cb0ef41Sopenharmony_ci bind(&if_code_is_off_heap); 61551cb0ef41Sopenharmony_ci Lw(scratch, FieldMemOperand(code_object, Code::kBuiltinIndexOffset)); 61561cb0ef41Sopenharmony_ci Dlsa(destination, kRootRegister, scratch, kSystemPointerSizeLog2); 61571cb0ef41Sopenharmony_ci Ld(destination, 61581cb0ef41Sopenharmony_ci MemOperand(destination, IsolateData::builtin_entry_table_offset())); 61591cb0ef41Sopenharmony_ci 61601cb0ef41Sopenharmony_ci bind(&out); 61611cb0ef41Sopenharmony_ci } else { 61621cb0ef41Sopenharmony_ci Daddu(destination, code_object, Code::kHeaderSize - kHeapObjectTag); 61631cb0ef41Sopenharmony_ci } 61641cb0ef41Sopenharmony_ci} 61651cb0ef41Sopenharmony_ci 61661cb0ef41Sopenharmony_civoid TurboAssembler::CallCodeObject(Register code_object) { 61671cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 61681cb0ef41Sopenharmony_ci LoadCodeObjectEntry(code_object, code_object); 61691cb0ef41Sopenharmony_ci Call(code_object); 61701cb0ef41Sopenharmony_ci} 61711cb0ef41Sopenharmony_ci 61721cb0ef41Sopenharmony_civoid TurboAssembler::JumpCodeObject(Register code_object, JumpMode jump_mode) { 61731cb0ef41Sopenharmony_ci ASM_CODE_COMMENT(this); 61741cb0ef41Sopenharmony_ci DCHECK_EQ(JumpMode::kJump, jump_mode); 61751cb0ef41Sopenharmony_ci LoadCodeObjectEntry(code_object, code_object); 61761cb0ef41Sopenharmony_ci Jump(code_object); 61771cb0ef41Sopenharmony_ci} 61781cb0ef41Sopenharmony_ci 61791cb0ef41Sopenharmony_ci} // namespace internal 61801cb0ef41Sopenharmony_ci} // namespace v8 61811cb0ef41Sopenharmony_ci 61821cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_MIPS64 6183