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