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