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