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#ifndef INCLUDED_FROM_MACRO_ASSEMBLER_H
61cb0ef41Sopenharmony_ci#error This header must be included via macro-assembler.h
71cb0ef41Sopenharmony_ci#endif
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#ifndef V8_CODEGEN_MIPS_MACRO_ASSEMBLER_MIPS_H_
101cb0ef41Sopenharmony_ci#define V8_CODEGEN_MIPS_MACRO_ASSEMBLER_MIPS_H_
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include "src/codegen/assembler.h"
131cb0ef41Sopenharmony_ci#include "src/codegen/mips/assembler-mips.h"
141cb0ef41Sopenharmony_ci#include "src/common/globals.h"
151cb0ef41Sopenharmony_ci#include "src/objects/contexts.h"
161cb0ef41Sopenharmony_ci#include "src/objects/tagged-index.h"
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cinamespace v8 {
191cb0ef41Sopenharmony_cinamespace internal {
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci// Forward declarations
221cb0ef41Sopenharmony_cienum class AbortReason : uint8_t;
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci// Reserved Register Usage Summary.
251cb0ef41Sopenharmony_ci//
261cb0ef41Sopenharmony_ci// Registers t8, t9, and at are reserved for use by the MacroAssembler.
271cb0ef41Sopenharmony_ci//
281cb0ef41Sopenharmony_ci// The programmer should know that the MacroAssembler may clobber these three,
291cb0ef41Sopenharmony_ci// but won't touch other registers except in special cases.
301cb0ef41Sopenharmony_ci//
311cb0ef41Sopenharmony_ci// Per the MIPS ABI, register t9 must be used for indirect function call
321cb0ef41Sopenharmony_ci// via 'jalr t9' or 'jr t9' instructions. This is relied upon by gcc when
331cb0ef41Sopenharmony_ci// trying to update gp register for position-independent-code. Whenever
341cb0ef41Sopenharmony_ci// MIPS generated code calls C code, it must be via t9 register.
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci// Flags used for LeaveExitFrame function.
371cb0ef41Sopenharmony_cienum LeaveExitFrameMode { EMIT_RETURN = true, NO_EMIT_RETURN = false };
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci// Flags used for the li macro-assembler function.
401cb0ef41Sopenharmony_cienum LiFlags {
411cb0ef41Sopenharmony_ci  // If the constant value can be represented in just 16 bits, then
421cb0ef41Sopenharmony_ci  // optimize the li to use a single instruction, rather than lui/ori pair.
431cb0ef41Sopenharmony_ci  OPTIMIZE_SIZE = 0,
441cb0ef41Sopenharmony_ci  // Always use 2 instructions (lui/ori pair), even if the constant could
451cb0ef41Sopenharmony_ci  // be loaded with just one, so that this value is patchable later.
461cb0ef41Sopenharmony_ci  CONSTANT_SIZE = 1
471cb0ef41Sopenharmony_ci};
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_cienum RAStatus { kRAHasNotBeenSaved, kRAHasBeenSaved };
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ciRegister GetRegisterThatIsNotOneOf(Register reg1, Register reg2 = no_reg,
521cb0ef41Sopenharmony_ci                                   Register reg3 = no_reg,
531cb0ef41Sopenharmony_ci                                   Register reg4 = no_reg,
541cb0ef41Sopenharmony_ci                                   Register reg5 = no_reg,
551cb0ef41Sopenharmony_ci                                   Register reg6 = no_reg);
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci// -----------------------------------------------------------------------------
581cb0ef41Sopenharmony_ci// Static helper functions.
591cb0ef41Sopenharmony_ci// Generate a MemOperand for loading a field from an object.
601cb0ef41Sopenharmony_ciinline MemOperand FieldMemOperand(Register object, int offset) {
611cb0ef41Sopenharmony_ci  return MemOperand(object, offset - kHeapObjectTag);
621cb0ef41Sopenharmony_ci}
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci// Generate a MemOperand for storing arguments 5..N on the stack
651cb0ef41Sopenharmony_ci// when calling CallCFunction().
661cb0ef41Sopenharmony_ciinline MemOperand CFunctionArgumentOperand(int index) {
671cb0ef41Sopenharmony_ci  DCHECK_GT(index, kCArgSlotCount);
681cb0ef41Sopenharmony_ci  // Argument 5 takes the slot just past the four Arg-slots.
691cb0ef41Sopenharmony_ci  int offset = (index - 5) * kPointerSize + kCArgsSlotsSize;
701cb0ef41Sopenharmony_ci  return MemOperand(sp, offset);
711cb0ef41Sopenharmony_ci}
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
741cb0ef41Sopenharmony_ci public:
751cb0ef41Sopenharmony_ci  using TurboAssemblerBase::TurboAssemblerBase;
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  // Activation support.
781cb0ef41Sopenharmony_ci  void EnterFrame(StackFrame::Type type);
791cb0ef41Sopenharmony_ci  void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg) {
801cb0ef41Sopenharmony_ci    // Out-of-line constant pool not implemented on mips.
811cb0ef41Sopenharmony_ci    UNREACHABLE();
821cb0ef41Sopenharmony_ci  }
831cb0ef41Sopenharmony_ci  void LeaveFrame(StackFrame::Type type);
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci  void AllocateStackSpace(Register bytes) { Subu(sp, sp, bytes); }
861cb0ef41Sopenharmony_ci  void AllocateStackSpace(int bytes) {
871cb0ef41Sopenharmony_ci    DCHECK_GE(bytes, 0);
881cb0ef41Sopenharmony_ci    if (bytes == 0) return;
891cb0ef41Sopenharmony_ci    Subu(sp, sp, Operand(bytes));
901cb0ef41Sopenharmony_ci  }
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  // Generates function and stub prologue code.
931cb0ef41Sopenharmony_ci  void StubPrologue(StackFrame::Type type);
941cb0ef41Sopenharmony_ci  void Prologue();
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  void InitializeRootRegister() {
971cb0ef41Sopenharmony_ci    ExternalReference isolate_root = ExternalReference::isolate_root(isolate());
981cb0ef41Sopenharmony_ci    li(kRootRegister, Operand(isolate_root));
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  // Jump unconditionally to given label.
1021cb0ef41Sopenharmony_ci  // We NEED a nop in the branch delay slot, as it used by v8, for example in
1031cb0ef41Sopenharmony_ci  // CodeGenerator::ProcessDeferred().
1041cb0ef41Sopenharmony_ci  // Currently the branch delay slot is filled by the MacroAssembler.
1051cb0ef41Sopenharmony_ci  // Use rather b(Label) for code generation.
1061cb0ef41Sopenharmony_ci  void jmp(Label* L) { Branch(L); }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  // -------------------------------------------------------------------------
1091cb0ef41Sopenharmony_ci  // Debugging.
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  void Trap();
1121cb0ef41Sopenharmony_ci  void DebugBreak();
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  // Calls Abort(msg) if the condition cc is not satisfied.
1151cb0ef41Sopenharmony_ci  // Use --debug_code to enable.
1161cb0ef41Sopenharmony_ci  void Assert(Condition cc, AbortReason reason, Register rs, Operand rt);
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  // Like Assert(), but always enabled.
1191cb0ef41Sopenharmony_ci  void Check(Condition cc, AbortReason reason, Register rs, Operand rt);
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci  // Print a message to stdout and abort execution.
1221cb0ef41Sopenharmony_ci  void Abort(AbortReason msg);
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  // Arguments macros.
1251cb0ef41Sopenharmony_ci#define COND_TYPED_ARGS Condition cond, Register r1, const Operand &r2
1261cb0ef41Sopenharmony_ci#define COND_ARGS cond, r1, r2
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci  // Cases when relocation is not needed.
1291cb0ef41Sopenharmony_ci#define DECLARE_NORELOC_PROTOTYPE(Name, target_type)                          \
1301cb0ef41Sopenharmony_ci  void Name(target_type target, BranchDelaySlot bd = PROTECT);                \
1311cb0ef41Sopenharmony_ci  inline void Name(BranchDelaySlot bd, target_type target) {                  \
1321cb0ef41Sopenharmony_ci    Name(target, bd);                                                         \
1331cb0ef41Sopenharmony_ci  }                                                                           \
1341cb0ef41Sopenharmony_ci  void Name(target_type target, COND_TYPED_ARGS,                              \
1351cb0ef41Sopenharmony_ci            BranchDelaySlot bd = PROTECT);                                    \
1361cb0ef41Sopenharmony_ci  inline void Name(BranchDelaySlot bd, target_type target, COND_TYPED_ARGS) { \
1371cb0ef41Sopenharmony_ci    Name(target, COND_ARGS, bd);                                              \
1381cb0ef41Sopenharmony_ci  }
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci#define DECLARE_BRANCH_PROTOTYPES(Name)   \
1411cb0ef41Sopenharmony_ci  DECLARE_NORELOC_PROTOTYPE(Name, Label*) \
1421cb0ef41Sopenharmony_ci  DECLARE_NORELOC_PROTOTYPE(Name, int32_t)
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci  DECLARE_BRANCH_PROTOTYPES(Branch)
1451cb0ef41Sopenharmony_ci  DECLARE_BRANCH_PROTOTYPES(BranchAndLink)
1461cb0ef41Sopenharmony_ci  DECLARE_BRANCH_PROTOTYPES(BranchShort)
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci#undef DECLARE_BRANCH_PROTOTYPES
1491cb0ef41Sopenharmony_ci#undef COND_TYPED_ARGS
1501cb0ef41Sopenharmony_ci#undef COND_ARGS
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  // Floating point branches
1531cb0ef41Sopenharmony_ci  void CompareF32(FPUCondition cc, FPURegister cmp1, FPURegister cmp2) {
1541cb0ef41Sopenharmony_ci    CompareF(S, cc, cmp1, cmp2);
1551cb0ef41Sopenharmony_ci  }
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  void CompareIsNanF32(FPURegister cmp1, FPURegister cmp2) {
1581cb0ef41Sopenharmony_ci    CompareIsNanF(S, cmp1, cmp2);
1591cb0ef41Sopenharmony_ci  }
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  void CompareF64(FPUCondition cc, FPURegister cmp1, FPURegister cmp2) {
1621cb0ef41Sopenharmony_ci    CompareF(D, cc, cmp1, cmp2);
1631cb0ef41Sopenharmony_ci  }
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci  void CompareIsNanF64(FPURegister cmp1, FPURegister cmp2) {
1661cb0ef41Sopenharmony_ci    CompareIsNanF(D, cmp1, cmp2);
1671cb0ef41Sopenharmony_ci  }
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  void BranchTrueShortF(Label* target, BranchDelaySlot bd = PROTECT);
1701cb0ef41Sopenharmony_ci  void BranchFalseShortF(Label* target, BranchDelaySlot bd = PROTECT);
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  void BranchTrueF(Label* target, BranchDelaySlot bd = PROTECT);
1731cb0ef41Sopenharmony_ci  void BranchFalseF(Label* target, BranchDelaySlot bd = PROTECT);
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  // MSA Branches
1761cb0ef41Sopenharmony_ci  void BranchMSA(Label* target, MSABranchDF df, MSABranchCondition cond,
1771cb0ef41Sopenharmony_ci                 MSARegister wt, BranchDelaySlot bd = PROTECT);
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  void BranchLong(int32_t offset, BranchDelaySlot bdslot = PROTECT);
1801cb0ef41Sopenharmony_ci  void Branch(Label* L, Condition cond, Register rs, RootIndex index,
1811cb0ef41Sopenharmony_ci              BranchDelaySlot bdslot = PROTECT);
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci  // Load int32 in the rd register.
1841cb0ef41Sopenharmony_ci  void li(Register rd, Operand j, LiFlags mode = OPTIMIZE_SIZE);
1851cb0ef41Sopenharmony_ci  inline void li(Register rd, int32_t j, LiFlags mode = OPTIMIZE_SIZE) {
1861cb0ef41Sopenharmony_ci    li(rd, Operand(j), mode);
1871cb0ef41Sopenharmony_ci  }
1881cb0ef41Sopenharmony_ci  void li(Register dst, Handle<HeapObject> value, LiFlags mode = OPTIMIZE_SIZE);
1891cb0ef41Sopenharmony_ci  void li(Register dst, ExternalReference value, LiFlags mode = OPTIMIZE_SIZE);
1901cb0ef41Sopenharmony_ci  void li(Register dst, const StringConstantBase* string,
1911cb0ef41Sopenharmony_ci          LiFlags mode = OPTIMIZE_SIZE);
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci  void LoadFromConstantsTable(Register destination, int constant_index) final;
1941cb0ef41Sopenharmony_ci  void LoadRootRegisterOffset(Register destination, intptr_t offset) final;
1951cb0ef41Sopenharmony_ci  void LoadRootRelative(Register destination, int32_t offset) final;
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  inline void Move(Register output, MemOperand operand) { Lw(output, operand); }
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci// Jump, Call, and Ret pseudo instructions implementing inter-working.
2001cb0ef41Sopenharmony_ci#define COND_ARGS                                  \
2011cb0ef41Sopenharmony_ci  Condition cond = al, Register rs = zero_reg,     \
2021cb0ef41Sopenharmony_ci            const Operand &rt = Operand(zero_reg), \
2031cb0ef41Sopenharmony_ci            BranchDelaySlot bd = PROTECT
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  void Jump(Register target, int16_t offset = 0, COND_ARGS);
2061cb0ef41Sopenharmony_ci  void Jump(Register target, Register base, int16_t offset = 0, COND_ARGS);
2071cb0ef41Sopenharmony_ci  void Jump(Register target, const Operand& offset, COND_ARGS);
2081cb0ef41Sopenharmony_ci  void Jump(intptr_t target, RelocInfo::Mode rmode, COND_ARGS);
2091cb0ef41Sopenharmony_ci  void Jump(Address target, RelocInfo::Mode rmode, COND_ARGS);
2101cb0ef41Sopenharmony_ci  // Deffer from li, this method save target to the memory, and then load
2111cb0ef41Sopenharmony_ci  // it to register use lw, it can be used in wasm jump table for concurrent
2121cb0ef41Sopenharmony_ci  // patching.
2131cb0ef41Sopenharmony_ci  void PatchAndJump(Address target);
2141cb0ef41Sopenharmony_ci  void Jump(Handle<Code> code, RelocInfo::Mode rmode, COND_ARGS);
2151cb0ef41Sopenharmony_ci  void Jump(const ExternalReference& reference);
2161cb0ef41Sopenharmony_ci  void Call(Register target, int16_t offset = 0, COND_ARGS);
2171cb0ef41Sopenharmony_ci  void Call(Register target, Register base, int16_t offset = 0, COND_ARGS);
2181cb0ef41Sopenharmony_ci  void Call(Address target, RelocInfo::Mode rmode, COND_ARGS);
2191cb0ef41Sopenharmony_ci  void Call(Handle<Code> code, RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
2201cb0ef41Sopenharmony_ci            COND_ARGS);
2211cb0ef41Sopenharmony_ci  void Call(Label* target);
2221cb0ef41Sopenharmony_ci  void LoadAddress(Register dst, Label* target);
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  // Load the builtin given by the Smi in |builtin| into the same
2251cb0ef41Sopenharmony_ci  // register.
2261cb0ef41Sopenharmony_ci  void LoadEntryFromBuiltinIndex(Register builtin);
2271cb0ef41Sopenharmony_ci  void LoadEntryFromBuiltin(Builtin builtin, Register destination);
2281cb0ef41Sopenharmony_ci  MemOperand EntryFromBuiltinAsOperand(Builtin builtin);
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ci  void CallBuiltinByIndex(Register builtin_index);
2311cb0ef41Sopenharmony_ci  void CallBuiltin(Builtin builtin);
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci  void LoadCodeObjectEntry(Register destination, Register code_object);
2341cb0ef41Sopenharmony_ci  void CallCodeObject(Register code_object);
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci  void JumpCodeObject(Register code_object,
2371cb0ef41Sopenharmony_ci                      JumpMode jump_mode = JumpMode::kJump);
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci  // Generates an instruction sequence s.t. the return address points to the
2401cb0ef41Sopenharmony_ci  // instruction following the call.
2411cb0ef41Sopenharmony_ci  // The return address on the stack is used by frame iteration.
2421cb0ef41Sopenharmony_ci  void StoreReturnAddressAndCall(Register target);
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci  void CallForDeoptimization(Builtin target, int deopt_id, Label* exit,
2451cb0ef41Sopenharmony_ci                             DeoptimizeKind kind, Label* ret,
2461cb0ef41Sopenharmony_ci                             Label* jump_deoptimization_entry_label);
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci  void Ret(COND_ARGS);
2491cb0ef41Sopenharmony_ci  inline void Ret(BranchDelaySlot bd, Condition cond = al,
2501cb0ef41Sopenharmony_ci                  Register rs = zero_reg,
2511cb0ef41Sopenharmony_ci                  const Operand& rt = Operand(zero_reg)) {
2521cb0ef41Sopenharmony_ci    Ret(cond, rs, rt, bd);
2531cb0ef41Sopenharmony_ci  }
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci  // Emit code to discard a non-negative number of pointer-sized elements
2561cb0ef41Sopenharmony_ci  // from the stack, clobbering only the sp register.
2571cb0ef41Sopenharmony_ci  void Drop(int count, Condition cond = cc_always, Register reg = no_reg,
2581cb0ef41Sopenharmony_ci            const Operand& op = Operand(no_reg));
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci  // We assume the size of the arguments is the pointer size.
2611cb0ef41Sopenharmony_ci  // An optional mode argument is passed, which can indicate we need to
2621cb0ef41Sopenharmony_ci  // explicitly add the receiver to the count.
2631cb0ef41Sopenharmony_ci  enum ArgumentsCountMode { kCountIncludesReceiver, kCountExcludesReceiver };
2641cb0ef41Sopenharmony_ci  enum ArgumentsCountType { kCountIsInteger, kCountIsSmi, kCountIsBytes };
2651cb0ef41Sopenharmony_ci  void DropArguments(Register count, ArgumentsCountType type,
2661cb0ef41Sopenharmony_ci                     ArgumentsCountMode mode);
2671cb0ef41Sopenharmony_ci  void DropArgumentsAndPushNewReceiver(Register argc, Register receiver,
2681cb0ef41Sopenharmony_ci                                       ArgumentsCountType type,
2691cb0ef41Sopenharmony_ci                                       ArgumentsCountMode mode);
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci  // Trivial case of DropAndRet that utilizes the delay slot.
2721cb0ef41Sopenharmony_ci  void DropAndRet(int drop);
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci  void DropAndRet(int drop, Condition cond, Register reg, const Operand& op);
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci  void Lw(Register rd, const MemOperand& rs);
2771cb0ef41Sopenharmony_ci  void Sw(Register rd, const MemOperand& rs);
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci  void push(Register src) {
2801cb0ef41Sopenharmony_ci    Addu(sp, sp, Operand(-kPointerSize));
2811cb0ef41Sopenharmony_ci    sw(src, MemOperand(sp, 0));
2821cb0ef41Sopenharmony_ci  }
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci  void Push(Register src) { push(src); }
2851cb0ef41Sopenharmony_ci  void Push(Handle<HeapObject> handle);
2861cb0ef41Sopenharmony_ci  void Push(Smi smi);
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci  // Push two registers. Pushes leftmost register first (to highest address).
2891cb0ef41Sopenharmony_ci  void Push(Register src1, Register src2) {
2901cb0ef41Sopenharmony_ci    Subu(sp, sp, Operand(2 * kPointerSize));
2911cb0ef41Sopenharmony_ci    sw(src1, MemOperand(sp, 1 * kPointerSize));
2921cb0ef41Sopenharmony_ci    sw(src2, MemOperand(sp, 0 * kPointerSize));
2931cb0ef41Sopenharmony_ci  }
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci  // Push three registers. Pushes leftmost register first (to highest address).
2961cb0ef41Sopenharmony_ci  void Push(Register src1, Register src2, Register src3) {
2971cb0ef41Sopenharmony_ci    Subu(sp, sp, Operand(3 * kPointerSize));
2981cb0ef41Sopenharmony_ci    sw(src1, MemOperand(sp, 2 * kPointerSize));
2991cb0ef41Sopenharmony_ci    sw(src2, MemOperand(sp, 1 * kPointerSize));
3001cb0ef41Sopenharmony_ci    sw(src3, MemOperand(sp, 0 * kPointerSize));
3011cb0ef41Sopenharmony_ci  }
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci  // Push four registers. Pushes leftmost register first (to highest address).
3041cb0ef41Sopenharmony_ci  void Push(Register src1, Register src2, Register src3, Register src4) {
3051cb0ef41Sopenharmony_ci    Subu(sp, sp, Operand(4 * kPointerSize));
3061cb0ef41Sopenharmony_ci    sw(src1, MemOperand(sp, 3 * kPointerSize));
3071cb0ef41Sopenharmony_ci    sw(src2, MemOperand(sp, 2 * kPointerSize));
3081cb0ef41Sopenharmony_ci    sw(src3, MemOperand(sp, 1 * kPointerSize));
3091cb0ef41Sopenharmony_ci    sw(src4, MemOperand(sp, 0 * kPointerSize));
3101cb0ef41Sopenharmony_ci  }
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci  // Push five registers. Pushes leftmost register first (to highest address).
3131cb0ef41Sopenharmony_ci  void Push(Register src1, Register src2, Register src3, Register src4,
3141cb0ef41Sopenharmony_ci            Register src5) {
3151cb0ef41Sopenharmony_ci    Subu(sp, sp, Operand(5 * kPointerSize));
3161cb0ef41Sopenharmony_ci    sw(src1, MemOperand(sp, 4 * kPointerSize));
3171cb0ef41Sopenharmony_ci    sw(src2, MemOperand(sp, 3 * kPointerSize));
3181cb0ef41Sopenharmony_ci    sw(src3, MemOperand(sp, 2 * kPointerSize));
3191cb0ef41Sopenharmony_ci    sw(src4, MemOperand(sp, 1 * kPointerSize));
3201cb0ef41Sopenharmony_ci    sw(src5, MemOperand(sp, 0 * kPointerSize));
3211cb0ef41Sopenharmony_ci  }
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci  void Push(Register src, Condition cond, Register tst1, Register tst2) {
3241cb0ef41Sopenharmony_ci    // Since we don't have conditional execution we use a Branch.
3251cb0ef41Sopenharmony_ci    Branch(3, cond, tst1, Operand(tst2));
3261cb0ef41Sopenharmony_ci    Subu(sp, sp, Operand(kPointerSize));
3271cb0ef41Sopenharmony_ci    sw(src, MemOperand(sp, 0));
3281cb0ef41Sopenharmony_ci  }
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci  enum PushArrayOrder { kNormal, kReverse };
3311cb0ef41Sopenharmony_ci  void PushArray(Register array, Register size, Register scratch,
3321cb0ef41Sopenharmony_ci                 Register scratch2, PushArrayOrder order = kNormal);
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_ci  void MaybeSaveRegisters(RegList registers);
3351cb0ef41Sopenharmony_ci  void MaybeRestoreRegisters(RegList registers);
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_ci  void CallEphemeronKeyBarrier(Register object, Register slot_address,
3381cb0ef41Sopenharmony_ci                               SaveFPRegsMode fp_mode);
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci  void CallRecordWriteStubSaveRegisters(
3411cb0ef41Sopenharmony_ci      Register object, Register slot_address,
3421cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
3431cb0ef41Sopenharmony_ci      StubCallMode mode = StubCallMode::kCallBuiltinPointer);
3441cb0ef41Sopenharmony_ci  void CallRecordWriteStub(
3451cb0ef41Sopenharmony_ci      Register object, Register slot_address,
3461cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
3471cb0ef41Sopenharmony_ci      StubCallMode mode = StubCallMode::kCallBuiltinPointer);
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ci  // Push multiple registers on the stack.
3501cb0ef41Sopenharmony_ci  // Registers are saved in numerical order, with higher numbered registers
3511cb0ef41Sopenharmony_ci  // saved in higher memory addresses.
3521cb0ef41Sopenharmony_ci  void MultiPush(RegList regs);
3531cb0ef41Sopenharmony_ci  void MultiPushFPU(DoubleRegList regs);
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_ci  // Calculate how much stack space (in bytes) are required to store caller
3561cb0ef41Sopenharmony_ci  // registers excluding those specified in the arguments.
3571cb0ef41Sopenharmony_ci  int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
3581cb0ef41Sopenharmony_ci                                      Register exclusion1 = no_reg,
3591cb0ef41Sopenharmony_ci                                      Register exclusion2 = no_reg,
3601cb0ef41Sopenharmony_ci                                      Register exclusion3 = no_reg) const;
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci  // Push caller saved registers on the stack, and return the number of bytes
3631cb0ef41Sopenharmony_ci  // stack pointer is adjusted.
3641cb0ef41Sopenharmony_ci  int PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
3651cb0ef41Sopenharmony_ci                      Register exclusion2 = no_reg,
3661cb0ef41Sopenharmony_ci                      Register exclusion3 = no_reg);
3671cb0ef41Sopenharmony_ci  // Restore caller saved registers from the stack, and return the number of
3681cb0ef41Sopenharmony_ci  // bytes stack pointer is adjusted.
3691cb0ef41Sopenharmony_ci  int PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
3701cb0ef41Sopenharmony_ci                     Register exclusion2 = no_reg,
3711cb0ef41Sopenharmony_ci                     Register exclusion3 = no_reg);
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci  void pop(Register dst) {
3741cb0ef41Sopenharmony_ci    lw(dst, MemOperand(sp, 0));
3751cb0ef41Sopenharmony_ci    Addu(sp, sp, Operand(kPointerSize));
3761cb0ef41Sopenharmony_ci  }
3771cb0ef41Sopenharmony_ci
3781cb0ef41Sopenharmony_ci  void Pop(Register dst) { pop(dst); }
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci  // Pop two registers. Pops rightmost register first (from lower address).
3811cb0ef41Sopenharmony_ci  void Pop(Register src1, Register src2) {
3821cb0ef41Sopenharmony_ci    DCHECK(src1 != src2);
3831cb0ef41Sopenharmony_ci    lw(src2, MemOperand(sp, 0 * kPointerSize));
3841cb0ef41Sopenharmony_ci    lw(src1, MemOperand(sp, 1 * kPointerSize));
3851cb0ef41Sopenharmony_ci    Addu(sp, sp, 2 * kPointerSize);
3861cb0ef41Sopenharmony_ci  }
3871cb0ef41Sopenharmony_ci
3881cb0ef41Sopenharmony_ci  // Pop three registers. Pops rightmost register first (from lower address).
3891cb0ef41Sopenharmony_ci  void Pop(Register src1, Register src2, Register src3) {
3901cb0ef41Sopenharmony_ci    lw(src3, MemOperand(sp, 0 * kPointerSize));
3911cb0ef41Sopenharmony_ci    lw(src2, MemOperand(sp, 1 * kPointerSize));
3921cb0ef41Sopenharmony_ci    lw(src1, MemOperand(sp, 2 * kPointerSize));
3931cb0ef41Sopenharmony_ci    Addu(sp, sp, 3 * kPointerSize);
3941cb0ef41Sopenharmony_ci  }
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ci  void Pop(uint32_t count = 1) { Addu(sp, sp, Operand(count * kPointerSize)); }
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_ci  // Pops multiple values from the stack and load them in the
3991cb0ef41Sopenharmony_ci  // registers specified in regs. Pop order is the opposite as in MultiPush.
4001cb0ef41Sopenharmony_ci  void MultiPop(RegList regs);
4011cb0ef41Sopenharmony_ci  void MultiPopFPU(DoubleRegList regs);
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ci  // Load Scaled Address instructions. Parameter sa (shift argument) must be
4041cb0ef41Sopenharmony_ci  // between [1, 31] (inclusive). On pre-r6 architectures the scratch register
4051cb0ef41Sopenharmony_ci  // may be clobbered.
4061cb0ef41Sopenharmony_ci  void Lsa(Register rd, Register rs, Register rt, uint8_t sa,
4071cb0ef41Sopenharmony_ci           Register scratch = at);
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci#define DEFINE_INSTRUCTION(instr)                          \
4101cb0ef41Sopenharmony_ci  void instr(Register rd, Register rs, const Operand& rt); \
4111cb0ef41Sopenharmony_ci  void instr(Register rd, Register rs, Register rt) {      \
4121cb0ef41Sopenharmony_ci    instr(rd, rs, Operand(rt));                            \
4131cb0ef41Sopenharmony_ci  }                                                        \
4141cb0ef41Sopenharmony_ci  void instr(Register rs, Register rt, int32_t j) { instr(rs, rt, Operand(j)); }
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci#define DEFINE_INSTRUCTION2(instr)                                 \
4171cb0ef41Sopenharmony_ci  void instr(Register rs, const Operand& rt);                      \
4181cb0ef41Sopenharmony_ci  void instr(Register rs, Register rt) { instr(rs, Operand(rt)); } \
4191cb0ef41Sopenharmony_ci  void instr(Register rs, int32_t j) { instr(rs, Operand(j)); }
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_ci#define DEFINE_INSTRUCTION3(instr)                                            \
4221cb0ef41Sopenharmony_ci  void instr(Register rd_hi, Register rd_lo, Register rs, const Operand& rt); \
4231cb0ef41Sopenharmony_ci  void instr(Register rd_hi, Register rd_lo, Register rs, Register rt) {      \
4241cb0ef41Sopenharmony_ci    instr(rd_hi, rd_lo, rs, Operand(rt));                                     \
4251cb0ef41Sopenharmony_ci  }                                                                           \
4261cb0ef41Sopenharmony_ci  void instr(Register rd_hi, Register rd_lo, Register rs, int32_t j) {        \
4271cb0ef41Sopenharmony_ci    instr(rd_hi, rd_lo, rs, Operand(j));                                      \
4281cb0ef41Sopenharmony_ci  }
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Addu)
4311cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Subu)
4321cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Mul)
4331cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Div)
4341cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Divu)
4351cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Mod)
4361cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Modu)
4371cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Mulh)
4381cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION2(Mult)
4391cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Mulhu)
4401cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION2(Multu)
4411cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION2(Div)
4421cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION2(Divu)
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION3(Div)
4451cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION3(Mul)
4461cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION3(Mulu)
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(And)
4491cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Or)
4501cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Xor)
4511cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Nor)
4521cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION2(Neg)
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Slt)
4551cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Sltu)
4561cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Sle)
4571cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Sleu)
4581cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Sgt)
4591cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Sgtu)
4601cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Sge)
4611cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Sgeu)
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ci  // MIPS32 R2 instruction macro.
4641cb0ef41Sopenharmony_ci  DEFINE_INSTRUCTION(Ror)
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci#undef DEFINE_INSTRUCTION
4671cb0ef41Sopenharmony_ci#undef DEFINE_INSTRUCTION2
4681cb0ef41Sopenharmony_ci#undef DEFINE_INSTRUCTION3
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ci  void SmiUntag(Register reg) { sra(reg, reg, kSmiTagSize); }
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci  void SmiUntag(Register dst, Register src) { sra(dst, src, kSmiTagSize); }
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_ci  void SmiToInt32(Register smi) { SmiUntag(smi); }
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ci  int CalculateStackPassedWords(int num_reg_arguments,
4771cb0ef41Sopenharmony_ci                                int num_double_arguments);
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_ci  // Before calling a C-function from generated code, align arguments on stack
4801cb0ef41Sopenharmony_ci  // and add space for the four mips argument slots.
4811cb0ef41Sopenharmony_ci  // After aligning the frame, non-register arguments must be stored on the
4821cb0ef41Sopenharmony_ci  // stack, after the argument-slots using helper: CFunctionArgumentOperand().
4831cb0ef41Sopenharmony_ci  // The argument count assumes all arguments are word sized.
4841cb0ef41Sopenharmony_ci  // Some compilers/platforms require the stack to be aligned when calling
4851cb0ef41Sopenharmony_ci  // C++ code.
4861cb0ef41Sopenharmony_ci  // Needs a scratch register to do some arithmetic. This register will be
4871cb0ef41Sopenharmony_ci  // trashed.
4881cb0ef41Sopenharmony_ci  void PrepareCallCFunction(int num_reg_arguments, int num_double_registers,
4891cb0ef41Sopenharmony_ci                            Register scratch);
4901cb0ef41Sopenharmony_ci  void PrepareCallCFunction(int num_reg_arguments, Register scratch);
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci  // Arguments 1-4 are placed in registers a0 through a3 respectively.
4931cb0ef41Sopenharmony_ci  // Arguments 5..n are stored to stack using following:
4941cb0ef41Sopenharmony_ci  //  sw(t0, CFunctionArgumentOperand(5));
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_ci  // Calls a C function and cleans up the space for arguments allocated
4971cb0ef41Sopenharmony_ci  // by PrepareCallCFunction. The called function is not allowed to trigger a
4981cb0ef41Sopenharmony_ci  // garbage collection, since that might move the code and invalidate the
4991cb0ef41Sopenharmony_ci  // return address (unless this is somehow accounted for by the called
5001cb0ef41Sopenharmony_ci  // function).
5011cb0ef41Sopenharmony_ci  void CallCFunction(ExternalReference function, int num_arguments);
5021cb0ef41Sopenharmony_ci  void CallCFunction(Register function, int num_arguments);
5031cb0ef41Sopenharmony_ci  void CallCFunction(ExternalReference function, int num_reg_arguments,
5041cb0ef41Sopenharmony_ci                     int num_double_arguments);
5051cb0ef41Sopenharmony_ci  void CallCFunction(Register function, int num_reg_arguments,
5061cb0ef41Sopenharmony_ci                     int num_double_arguments);
5071cb0ef41Sopenharmony_ci  void MovFromFloatResult(DoubleRegister dst);
5081cb0ef41Sopenharmony_ci  void MovFromFloatParameter(DoubleRegister dst);
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_ci  // There are two ways of passing double arguments on MIPS, depending on
5111cb0ef41Sopenharmony_ci  // whether soft or hard floating point ABI is used. These functions
5121cb0ef41Sopenharmony_ci  // abstract parameter passing for the three different ways we call
5131cb0ef41Sopenharmony_ci  // C functions from generated code.
5141cb0ef41Sopenharmony_ci  void MovToFloatParameter(DoubleRegister src);
5151cb0ef41Sopenharmony_ci  void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2);
5161cb0ef41Sopenharmony_ci  void MovToFloatResult(DoubleRegister src);
5171cb0ef41Sopenharmony_ci
5181cb0ef41Sopenharmony_ci  // See comments at the beginning of Builtins::Generate_CEntry.
5191cb0ef41Sopenharmony_ci  inline void PrepareCEntryArgs(int num_args) { li(a0, num_args); }
5201cb0ef41Sopenharmony_ci  inline void PrepareCEntryFunction(const ExternalReference& ref) {
5211cb0ef41Sopenharmony_ci    li(a1, ref);
5221cb0ef41Sopenharmony_ci  }
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci  void CheckPageFlag(Register object, Register scratch, int mask, Condition cc,
5251cb0ef41Sopenharmony_ci                     Label* condition_met);
5261cb0ef41Sopenharmony_ci#undef COND_ARGS
5271cb0ef41Sopenharmony_ci
5281cb0ef41Sopenharmony_ci  // Performs a truncating conversion of a floating point number as used by
5291cb0ef41Sopenharmony_ci  // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
5301cb0ef41Sopenharmony_ci  // Exits with 'result' holding the answer.
5311cb0ef41Sopenharmony_ci  void TruncateDoubleToI(Isolate* isolate, Zone* zone, Register result,
5321cb0ef41Sopenharmony_ci                         DoubleRegister double_input, StubCallMode stub_mode);
5331cb0ef41Sopenharmony_ci
5341cb0ef41Sopenharmony_ci  // Conditional move.
5351cb0ef41Sopenharmony_ci  void Movz(Register rd, Register rs, Register rt);
5361cb0ef41Sopenharmony_ci  void Movn(Register rd, Register rs, Register rt);
5371cb0ef41Sopenharmony_ci  void Movt(Register rd, Register rs, uint16_t cc = 0);
5381cb0ef41Sopenharmony_ci  void Movf(Register rd, Register rs, uint16_t cc = 0);
5391cb0ef41Sopenharmony_ci
5401cb0ef41Sopenharmony_ci  void LoadZeroIfFPUCondition(Register dest);
5411cb0ef41Sopenharmony_ci  void LoadZeroIfNotFPUCondition(Register dest);
5421cb0ef41Sopenharmony_ci
5431cb0ef41Sopenharmony_ci  void LoadZeroIfConditionNotZero(Register dest, Register condition);
5441cb0ef41Sopenharmony_ci  void LoadZeroIfConditionZero(Register dest, Register condition);
5451cb0ef41Sopenharmony_ci  void LoadZeroOnCondition(Register rd, Register rs, const Operand& rt,
5461cb0ef41Sopenharmony_ci                           Condition cond);
5471cb0ef41Sopenharmony_ci
5481cb0ef41Sopenharmony_ci  void Clz(Register rd, Register rs);
5491cb0ef41Sopenharmony_ci  void Ctz(Register rd, Register rs);
5501cb0ef41Sopenharmony_ci  void Popcnt(Register rd, Register rs);
5511cb0ef41Sopenharmony_ci
5521cb0ef41Sopenharmony_ci  // Int64Lowering instructions
5531cb0ef41Sopenharmony_ci  void AddPair(Register dst_low, Register dst_high, Register left_low,
5541cb0ef41Sopenharmony_ci               Register left_high, Register right_low, Register right_high,
5551cb0ef41Sopenharmony_ci               Register scratch1, Register scratch2);
5561cb0ef41Sopenharmony_ci
5571cb0ef41Sopenharmony_ci  void AddPair(Register dst_low, Register dst_high, Register left_low,
5581cb0ef41Sopenharmony_ci               Register left_high, int32_t imm, Register scratch1,
5591cb0ef41Sopenharmony_ci               Register scratch2);
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_ci  void SubPair(Register dst_low, Register dst_high, Register left_low,
5621cb0ef41Sopenharmony_ci               Register left_high, Register right_low, Register right_high,
5631cb0ef41Sopenharmony_ci               Register scratch1, Register scratch2);
5641cb0ef41Sopenharmony_ci
5651cb0ef41Sopenharmony_ci  void AndPair(Register dst_low, Register dst_high, Register left_low,
5661cb0ef41Sopenharmony_ci               Register left_high, Register right_low, Register right_high);
5671cb0ef41Sopenharmony_ci
5681cb0ef41Sopenharmony_ci  void OrPair(Register dst_low, Register dst_high, Register left_low,
5691cb0ef41Sopenharmony_ci              Register left_high, Register right_low, Register right_high);
5701cb0ef41Sopenharmony_ci
5711cb0ef41Sopenharmony_ci  void XorPair(Register dst_low, Register dst_high, Register left_low,
5721cb0ef41Sopenharmony_ci               Register left_high, Register right_low, Register right_high);
5731cb0ef41Sopenharmony_ci
5741cb0ef41Sopenharmony_ci  void MulPair(Register dst_low, Register dst_high, Register left_low,
5751cb0ef41Sopenharmony_ci               Register left_high, Register right_low, Register right_high,
5761cb0ef41Sopenharmony_ci               Register scratch1, Register scratch2);
5771cb0ef41Sopenharmony_ci
5781cb0ef41Sopenharmony_ci  void ShlPair(Register dst_low, Register dst_high, Register src_low,
5791cb0ef41Sopenharmony_ci               Register src_high, Register shift, Register scratch1,
5801cb0ef41Sopenharmony_ci               Register scratch2);
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci  void ShlPair(Register dst_low, Register dst_high, Register src_low,
5831cb0ef41Sopenharmony_ci               Register src_high, uint32_t shift, Register scratch);
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ci  void ShrPair(Register dst_low, Register dst_high, Register src_low,
5861cb0ef41Sopenharmony_ci               Register src_high, Register shift, Register scratch1,
5871cb0ef41Sopenharmony_ci               Register scratch2);
5881cb0ef41Sopenharmony_ci
5891cb0ef41Sopenharmony_ci  void ShrPair(Register dst_low, Register dst_high, Register src_low,
5901cb0ef41Sopenharmony_ci               Register src_high, uint32_t shift, Register scratch);
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_ci  void SarPair(Register dst_low, Register dst_high, Register src_low,
5931cb0ef41Sopenharmony_ci               Register src_high, Register shift, Register scratch1,
5941cb0ef41Sopenharmony_ci               Register scratch2);
5951cb0ef41Sopenharmony_ci
5961cb0ef41Sopenharmony_ci  void SarPair(Register dst_low, Register dst_high, Register src_low,
5971cb0ef41Sopenharmony_ci               Register src_high, uint32_t shift, Register scratch);
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci  // MIPS32 R2 instruction macro.
6001cb0ef41Sopenharmony_ci  void Ins(Register rt, Register rs, uint16_t pos, uint16_t size);
6011cb0ef41Sopenharmony_ci  void Ext(Register rt, Register rs, uint16_t pos, uint16_t size);
6021cb0ef41Sopenharmony_ci  void ExtractBits(Register dest, Register source, Register pos, int size,
6031cb0ef41Sopenharmony_ci                   bool sign_extend = false);
6041cb0ef41Sopenharmony_ci  void InsertBits(Register dest, Register source, Register pos, int size);
6051cb0ef41Sopenharmony_ci
6061cb0ef41Sopenharmony_ci  void Seb(Register rd, Register rt);
6071cb0ef41Sopenharmony_ci  void Seh(Register rd, Register rt);
6081cb0ef41Sopenharmony_ci  void Neg_s(FPURegister fd, FPURegister fs);
6091cb0ef41Sopenharmony_ci  void Neg_d(FPURegister fd, FPURegister fs);
6101cb0ef41Sopenharmony_ci
6111cb0ef41Sopenharmony_ci  // MIPS32 R6 instruction macros.
6121cb0ef41Sopenharmony_ci  void Bovc(Register rt, Register rs, Label* L);
6131cb0ef41Sopenharmony_ci  void Bnvc(Register rt, Register rs, Label* L);
6141cb0ef41Sopenharmony_ci
6151cb0ef41Sopenharmony_ci  // Convert single to unsigned word.
6161cb0ef41Sopenharmony_ci  void Trunc_uw_s(FPURegister fd, FPURegister fs, FPURegister scratch);
6171cb0ef41Sopenharmony_ci  void Trunc_uw_s(Register rd, FPURegister fs, FPURegister scratch);
6181cb0ef41Sopenharmony_ci
6191cb0ef41Sopenharmony_ci  void Trunc_w_d(FPURegister fd, FPURegister fs);
6201cb0ef41Sopenharmony_ci  void Round_w_d(FPURegister fd, FPURegister fs);
6211cb0ef41Sopenharmony_ci  void Floor_w_d(FPURegister fd, FPURegister fs);
6221cb0ef41Sopenharmony_ci  void Ceil_w_d(FPURegister fd, FPURegister fs);
6231cb0ef41Sopenharmony_ci
6241cb0ef41Sopenharmony_ci  // Round double functions
6251cb0ef41Sopenharmony_ci  void Trunc_d_d(FPURegister fd, FPURegister fs);
6261cb0ef41Sopenharmony_ci  void Round_d_d(FPURegister fd, FPURegister fs);
6271cb0ef41Sopenharmony_ci  void Floor_d_d(FPURegister fd, FPURegister fs);
6281cb0ef41Sopenharmony_ci  void Ceil_d_d(FPURegister fd, FPURegister fs);
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci  // Round float functions
6311cb0ef41Sopenharmony_ci  void Trunc_s_s(FPURegister fd, FPURegister fs);
6321cb0ef41Sopenharmony_ci  void Round_s_s(FPURegister fd, FPURegister fs);
6331cb0ef41Sopenharmony_ci  void Floor_s_s(FPURegister fd, FPURegister fs);
6341cb0ef41Sopenharmony_ci  void Ceil_s_s(FPURegister fd, FPURegister fs);
6351cb0ef41Sopenharmony_ci
6361cb0ef41Sopenharmony_ci  // FP32 mode: Move the general purpose register into
6371cb0ef41Sopenharmony_ci  // the high part of the double-register pair.
6381cb0ef41Sopenharmony_ci  // FP64 mode: Move the general-purpose register into
6391cb0ef41Sopenharmony_ci  // the higher 32 bits of the 64-bit coprocessor register,
6401cb0ef41Sopenharmony_ci  // while leaving the low bits unchanged.
6411cb0ef41Sopenharmony_ci  void Mthc1(Register rt, FPURegister fs);
6421cb0ef41Sopenharmony_ci
6431cb0ef41Sopenharmony_ci  // FP32 mode: move the high part of the double-register pair into
6441cb0ef41Sopenharmony_ci  // general purpose register.
6451cb0ef41Sopenharmony_ci  // FP64 mode: Move the higher 32 bits of the 64-bit coprocessor register into
6461cb0ef41Sopenharmony_ci  // general-purpose register.
6471cb0ef41Sopenharmony_ci  void Mfhc1(Register rt, FPURegister fs);
6481cb0ef41Sopenharmony_ci
6491cb0ef41Sopenharmony_ci  void Madd_s(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft,
6501cb0ef41Sopenharmony_ci              FPURegister scratch);
6511cb0ef41Sopenharmony_ci  void Madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft,
6521cb0ef41Sopenharmony_ci              FPURegister scratch);
6531cb0ef41Sopenharmony_ci  void Msub_s(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft,
6541cb0ef41Sopenharmony_ci              FPURegister scratch);
6551cb0ef41Sopenharmony_ci  void Msub_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft,
6561cb0ef41Sopenharmony_ci              FPURegister scratch);
6571cb0ef41Sopenharmony_ci
6581cb0ef41Sopenharmony_ci  // Change endianness
6591cb0ef41Sopenharmony_ci  void ByteSwapSigned(Register dest, Register src, int operand_size);
6601cb0ef41Sopenharmony_ci  void ByteSwapUnsigned(Register dest, Register src, int operand_size);
6611cb0ef41Sopenharmony_ci
6621cb0ef41Sopenharmony_ci  void Ulh(Register rd, const MemOperand& rs);
6631cb0ef41Sopenharmony_ci  void Ulhu(Register rd, const MemOperand& rs);
6641cb0ef41Sopenharmony_ci  void Ush(Register rd, const MemOperand& rs, Register scratch);
6651cb0ef41Sopenharmony_ci
6661cb0ef41Sopenharmony_ci  void Ulw(Register rd, const MemOperand& rs);
6671cb0ef41Sopenharmony_ci  void Usw(Register rd, const MemOperand& rs);
6681cb0ef41Sopenharmony_ci
6691cb0ef41Sopenharmony_ci  void Ulwc1(FPURegister fd, const MemOperand& rs, Register scratch);
6701cb0ef41Sopenharmony_ci  void Uswc1(FPURegister fd, const MemOperand& rs, Register scratch);
6711cb0ef41Sopenharmony_ci
6721cb0ef41Sopenharmony_ci  void Uldc1(FPURegister fd, const MemOperand& rs, Register scratch);
6731cb0ef41Sopenharmony_ci  void Usdc1(FPURegister fd, const MemOperand& rs, Register scratch);
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_ci  void Ldc1(FPURegister fd, const MemOperand& src);
6761cb0ef41Sopenharmony_ci  void Sdc1(FPURegister fs, const MemOperand& dst);
6771cb0ef41Sopenharmony_ci
6781cb0ef41Sopenharmony_ci  void Ll(Register rd, const MemOperand& rs);
6791cb0ef41Sopenharmony_ci  void Sc(Register rd, const MemOperand& rs);
6801cb0ef41Sopenharmony_ci
6811cb0ef41Sopenharmony_ci  // Perform a floating-point min or max operation with the
6821cb0ef41Sopenharmony_ci  // (IEEE-754-compatible) semantics of MIPS32's Release 6 MIN.fmt/MAX.fmt.
6831cb0ef41Sopenharmony_ci  // Some cases, typically NaNs or +/-0.0, are expected to be rare and are
6841cb0ef41Sopenharmony_ci  // handled in out-of-line code. The specific behaviour depends on supported
6851cb0ef41Sopenharmony_ci  // instructions.
6861cb0ef41Sopenharmony_ci  //
6871cb0ef41Sopenharmony_ci  // These functions assume (and assert) that src1!=src2. It is permitted
6881cb0ef41Sopenharmony_ci  // for the result to alias either input register.
6891cb0ef41Sopenharmony_ci  void Float32Max(FPURegister dst, FPURegister src1, FPURegister src2,
6901cb0ef41Sopenharmony_ci                  Label* out_of_line);
6911cb0ef41Sopenharmony_ci  void Float32Min(FPURegister dst, FPURegister src1, FPURegister src2,
6921cb0ef41Sopenharmony_ci                  Label* out_of_line);
6931cb0ef41Sopenharmony_ci  void Float64Max(DoubleRegister dst, DoubleRegister src1, DoubleRegister src2,
6941cb0ef41Sopenharmony_ci                  Label* out_of_line);
6951cb0ef41Sopenharmony_ci  void Float64Min(DoubleRegister dst, DoubleRegister src1, DoubleRegister src2,
6961cb0ef41Sopenharmony_ci                  Label* out_of_line);
6971cb0ef41Sopenharmony_ci
6981cb0ef41Sopenharmony_ci  // Generate out-of-line cases for the macros above.
6991cb0ef41Sopenharmony_ci  void Float32MaxOutOfLine(FPURegister dst, FPURegister src1, FPURegister src2);
7001cb0ef41Sopenharmony_ci  void Float32MinOutOfLine(FPURegister dst, FPURegister src1, FPURegister src2);
7011cb0ef41Sopenharmony_ci  void Float64MaxOutOfLine(DoubleRegister dst, DoubleRegister src1,
7021cb0ef41Sopenharmony_ci                           DoubleRegister src2);
7031cb0ef41Sopenharmony_ci  void Float64MinOutOfLine(DoubleRegister dst, DoubleRegister src1,
7041cb0ef41Sopenharmony_ci                           DoubleRegister src2);
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_ci  bool IsDoubleZeroRegSet() { return has_double_zero_reg_set_; }
7071cb0ef41Sopenharmony_ci
7081cb0ef41Sopenharmony_ci  void mov(Register rd, Register rt) { or_(rd, rt, zero_reg); }
7091cb0ef41Sopenharmony_ci
7101cb0ef41Sopenharmony_ci  inline void Move(Register dst, Handle<HeapObject> handle) { li(dst, handle); }
7111cb0ef41Sopenharmony_ci  inline void Move(Register dst, Smi smi) { li(dst, Operand(smi)); }
7121cb0ef41Sopenharmony_ci
7131cb0ef41Sopenharmony_ci  inline void Move(Register dst, Register src) {
7141cb0ef41Sopenharmony_ci    if (dst != src) {
7151cb0ef41Sopenharmony_ci      mov(dst, src);
7161cb0ef41Sopenharmony_ci    }
7171cb0ef41Sopenharmony_ci  }
7181cb0ef41Sopenharmony_ci
7191cb0ef41Sopenharmony_ci  inline void Move_d(FPURegister dst, FPURegister src) {
7201cb0ef41Sopenharmony_ci    if (dst != src) {
7211cb0ef41Sopenharmony_ci      mov_d(dst, src);
7221cb0ef41Sopenharmony_ci    }
7231cb0ef41Sopenharmony_ci  }
7241cb0ef41Sopenharmony_ci
7251cb0ef41Sopenharmony_ci  inline void Move_s(FPURegister dst, FPURegister src) {
7261cb0ef41Sopenharmony_ci    if (dst != src) {
7271cb0ef41Sopenharmony_ci      mov_s(dst, src);
7281cb0ef41Sopenharmony_ci    }
7291cb0ef41Sopenharmony_ci  }
7301cb0ef41Sopenharmony_ci
7311cb0ef41Sopenharmony_ci  inline void Move(FPURegister dst, FPURegister src) { Move_d(dst, src); }
7321cb0ef41Sopenharmony_ci
7331cb0ef41Sopenharmony_ci  inline void Move(Register dst_low, Register dst_high, FPURegister src) {
7341cb0ef41Sopenharmony_ci    mfc1(dst_low, src);
7351cb0ef41Sopenharmony_ci    Mfhc1(dst_high, src);
7361cb0ef41Sopenharmony_ci  }
7371cb0ef41Sopenharmony_ci
7381cb0ef41Sopenharmony_ci  inline void FmoveHigh(Register dst_high, FPURegister src) {
7391cb0ef41Sopenharmony_ci    Mfhc1(dst_high, src);
7401cb0ef41Sopenharmony_ci  }
7411cb0ef41Sopenharmony_ci
7421cb0ef41Sopenharmony_ci  inline void FmoveHigh(FPURegister dst, Register src_high) {
7431cb0ef41Sopenharmony_ci    Mthc1(src_high, dst);
7441cb0ef41Sopenharmony_ci  }
7451cb0ef41Sopenharmony_ci
7461cb0ef41Sopenharmony_ci  inline void FmoveLow(Register dst_low, FPURegister src) {
7471cb0ef41Sopenharmony_ci    mfc1(dst_low, src);
7481cb0ef41Sopenharmony_ci  }
7491cb0ef41Sopenharmony_ci
7501cb0ef41Sopenharmony_ci  void FmoveLow(FPURegister dst, Register src_low);
7511cb0ef41Sopenharmony_ci
7521cb0ef41Sopenharmony_ci  inline void Move(FPURegister dst, Register src_low, Register src_high) {
7531cb0ef41Sopenharmony_ci    mtc1(src_low, dst);
7541cb0ef41Sopenharmony_ci    Mthc1(src_high, dst);
7551cb0ef41Sopenharmony_ci  }
7561cb0ef41Sopenharmony_ci
7571cb0ef41Sopenharmony_ci  void Move(FPURegister dst, float imm) { Move(dst, bit_cast<uint32_t>(imm)); }
7581cb0ef41Sopenharmony_ci  void Move(FPURegister dst, double imm) { Move(dst, bit_cast<uint64_t>(imm)); }
7591cb0ef41Sopenharmony_ci  void Move(FPURegister dst, uint32_t src);
7601cb0ef41Sopenharmony_ci  void Move(FPURegister dst, uint64_t src);
7611cb0ef41Sopenharmony_ci
7621cb0ef41Sopenharmony_ci  // -------------------------------------------------------------------------
7631cb0ef41Sopenharmony_ci  // Overflow operations.
7641cb0ef41Sopenharmony_ci
7651cb0ef41Sopenharmony_ci  // AddOverflow sets overflow register to a negative value if
7661cb0ef41Sopenharmony_ci  // overflow occured, otherwise it is zero or positive
7671cb0ef41Sopenharmony_ci  void AddOverflow(Register dst, Register left, const Operand& right,
7681cb0ef41Sopenharmony_ci                   Register overflow);
7691cb0ef41Sopenharmony_ci  // SubOverflow sets overflow register to a negative value if
7701cb0ef41Sopenharmony_ci  // overflow occured, otherwise it is zero or positive
7711cb0ef41Sopenharmony_ci  void SubOverflow(Register dst, Register left, const Operand& right,
7721cb0ef41Sopenharmony_ci                   Register overflow);
7731cb0ef41Sopenharmony_ci  // MulOverflow sets overflow register to zero if no overflow occured
7741cb0ef41Sopenharmony_ci  void MulOverflow(Register dst, Register left, const Operand& right,
7751cb0ef41Sopenharmony_ci                   Register overflow);
7761cb0ef41Sopenharmony_ci
7771cb0ef41Sopenharmony_ci// Number of instructions needed for calculation of switch table entry address
7781cb0ef41Sopenharmony_ci#ifdef _MIPS_ARCH_MIPS32R6
7791cb0ef41Sopenharmony_ci  static constexpr int kSwitchTablePrologueSize = 5;
7801cb0ef41Sopenharmony_ci#else
7811cb0ef41Sopenharmony_ci  static constexpr int kSwitchTablePrologueSize = 10;
7821cb0ef41Sopenharmony_ci#endif
7831cb0ef41Sopenharmony_ci  // GetLabelFunction must be lambda '[](size_t index) -> Label*' or a
7841cb0ef41Sopenharmony_ci  // functor/function with 'Label *func(size_t index)' declaration.
7851cb0ef41Sopenharmony_ci  template <typename Func>
7861cb0ef41Sopenharmony_ci  void GenerateSwitchTable(Register index, size_t case_count,
7871cb0ef41Sopenharmony_ci                           Func GetLabelFunction);
7881cb0ef41Sopenharmony_ci
7891cb0ef41Sopenharmony_ci  // Load an object from the root table.
7901cb0ef41Sopenharmony_ci  void LoadRoot(Register destination, RootIndex index) final;
7911cb0ef41Sopenharmony_ci  void LoadRoot(Register destination, RootIndex index, Condition cond,
7921cb0ef41Sopenharmony_ci                Register src1, const Operand& src2);
7931cb0ef41Sopenharmony_ci
7941cb0ef41Sopenharmony_ci  void LoadMap(Register destination, Register object);
7951cb0ef41Sopenharmony_ci
7961cb0ef41Sopenharmony_ci  // If the value is a NaN, canonicalize the value else, do nothing.
7971cb0ef41Sopenharmony_ci  void FPUCanonicalizeNaN(const DoubleRegister dst, const DoubleRegister src);
7981cb0ef41Sopenharmony_ci
7991cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
8001cb0ef41Sopenharmony_ci  // FPU macros. These do not handle special cases like NaN or +- inf.
8011cb0ef41Sopenharmony_ci
8021cb0ef41Sopenharmony_ci  // Convert unsigned word to double.
8031cb0ef41Sopenharmony_ci  void Cvt_d_uw(FPURegister fd, Register rs, FPURegister scratch);
8041cb0ef41Sopenharmony_ci
8051cb0ef41Sopenharmony_ci  // Convert double to unsigned word.
8061cb0ef41Sopenharmony_ci  void Trunc_uw_d(FPURegister fd, FPURegister fs, FPURegister scratch);
8071cb0ef41Sopenharmony_ci  void Trunc_uw_d(Register rd, FPURegister fs, FPURegister scratch);
8081cb0ef41Sopenharmony_ci
8091cb0ef41Sopenharmony_ci  // Jump the register contains a smi.
8101cb0ef41Sopenharmony_ci  void JumpIfSmi(Register value, Label* smi_label,
8111cb0ef41Sopenharmony_ci                 BranchDelaySlot bd = PROTECT);
8121cb0ef41Sopenharmony_ci
8131cb0ef41Sopenharmony_ci  void JumpIfEqual(Register a, int32_t b, Label* dest) {
8141cb0ef41Sopenharmony_ci    li(kScratchReg, Operand(b));
8151cb0ef41Sopenharmony_ci    Branch(dest, eq, a, Operand(kScratchReg));
8161cb0ef41Sopenharmony_ci  }
8171cb0ef41Sopenharmony_ci
8181cb0ef41Sopenharmony_ci  void JumpIfLessThan(Register a, int32_t b, Label* dest) {
8191cb0ef41Sopenharmony_ci    li(kScratchReg, Operand(b));
8201cb0ef41Sopenharmony_ci    Branch(dest, lt, a, Operand(kScratchReg));
8211cb0ef41Sopenharmony_ci  }
8221cb0ef41Sopenharmony_ci
8231cb0ef41Sopenharmony_ci  // Push a standard frame, consisting of ra, fp, context and JS function.
8241cb0ef41Sopenharmony_ci  void PushStandardFrame(Register function_reg);
8251cb0ef41Sopenharmony_ci
8261cb0ef41Sopenharmony_ci  // Get the actual activation frame alignment for target environment.
8271cb0ef41Sopenharmony_ci  static int ActivationFrameAlignment();
8281cb0ef41Sopenharmony_ci
8291cb0ef41Sopenharmony_ci  // Compute the start of the generated instruction stream from the current PC.
8301cb0ef41Sopenharmony_ci  // This is an alternative to embedding the {CodeObject} handle as a reference.
8311cb0ef41Sopenharmony_ci  void ComputeCodeStartAddress(Register dst);
8321cb0ef41Sopenharmony_ci
8331cb0ef41Sopenharmony_ci  // Control-flow integrity:
8341cb0ef41Sopenharmony_ci
8351cb0ef41Sopenharmony_ci  // Define a function entrypoint. This doesn't emit any code for this
8361cb0ef41Sopenharmony_ci  // architecture, as control-flow integrity is not supported for it.
8371cb0ef41Sopenharmony_ci  void CodeEntry() {}
8381cb0ef41Sopenharmony_ci  // Define an exception handler.
8391cb0ef41Sopenharmony_ci  void ExceptionHandler() {}
8401cb0ef41Sopenharmony_ci  // Define an exception handler and bind a label.
8411cb0ef41Sopenharmony_ci  void BindExceptionHandler(Label* label) { bind(label); }
8421cb0ef41Sopenharmony_ci
8431cb0ef41Sopenharmony_ci protected:
8441cb0ef41Sopenharmony_ci  void BranchLong(Label* L, BranchDelaySlot bdslot);
8451cb0ef41Sopenharmony_ci
8461cb0ef41Sopenharmony_ci  inline Register GetRtAsRegisterHelper(const Operand& rt, Register scratch);
8471cb0ef41Sopenharmony_ci
8481cb0ef41Sopenharmony_ci  inline int32_t GetOffset(int32_t offset, Label* L, OffsetSize bits);
8491cb0ef41Sopenharmony_ci
8501cb0ef41Sopenharmony_ci private:
8511cb0ef41Sopenharmony_ci  bool has_double_zero_reg_set_ = false;
8521cb0ef41Sopenharmony_ci
8531cb0ef41Sopenharmony_ci  // Performs a truncating conversion of a floating point number as used by
8541cb0ef41Sopenharmony_ci  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
8551cb0ef41Sopenharmony_ci  // succeeds, otherwise falls through if result is saturated. On return
8561cb0ef41Sopenharmony_ci  // 'result' either holds answer, or is clobbered on fall through.
8571cb0ef41Sopenharmony_ci  void TryInlineTruncateDoubleToI(Register result, DoubleRegister input,
8581cb0ef41Sopenharmony_ci                                  Label* done);
8591cb0ef41Sopenharmony_ci
8601cb0ef41Sopenharmony_ci  void CallCFunctionHelper(Register function_base, int16_t function_offset,
8611cb0ef41Sopenharmony_ci                           int num_reg_arguments, int num_double_arguments);
8621cb0ef41Sopenharmony_ci
8631cb0ef41Sopenharmony_ci  void CompareF(SecondaryField sizeField, FPUCondition cc, FPURegister cmp1,
8641cb0ef41Sopenharmony_ci                FPURegister cmp2);
8651cb0ef41Sopenharmony_ci
8661cb0ef41Sopenharmony_ci  void CompareIsNanF(SecondaryField sizeField, FPURegister cmp1,
8671cb0ef41Sopenharmony_ci                     FPURegister cmp2);
8681cb0ef41Sopenharmony_ci
8691cb0ef41Sopenharmony_ci  void BranchShortMSA(MSABranchDF df, Label* target, MSABranchCondition cond,
8701cb0ef41Sopenharmony_ci                      MSARegister wt, BranchDelaySlot bd = PROTECT);
8711cb0ef41Sopenharmony_ci
8721cb0ef41Sopenharmony_ci  // TODO(mips) Reorder parameters so out parameters come last.
8731cb0ef41Sopenharmony_ci  bool CalculateOffset(Label* L, int32_t* offset, OffsetSize bits);
8741cb0ef41Sopenharmony_ci  bool CalculateOffset(Label* L, int32_t* offset, OffsetSize bits,
8751cb0ef41Sopenharmony_ci                       Register* scratch, const Operand& rt);
8761cb0ef41Sopenharmony_ci
8771cb0ef41Sopenharmony_ci  void BranchShortHelperR6(int32_t offset, Label* L);
8781cb0ef41Sopenharmony_ci  void BranchShortHelper(int16_t offset, Label* L, BranchDelaySlot bdslot);
8791cb0ef41Sopenharmony_ci  bool BranchShortHelperR6(int32_t offset, Label* L, Condition cond,
8801cb0ef41Sopenharmony_ci                           Register rs, const Operand& rt);
8811cb0ef41Sopenharmony_ci  bool BranchShortHelper(int16_t offset, Label* L, Condition cond, Register rs,
8821cb0ef41Sopenharmony_ci                         const Operand& rt, BranchDelaySlot bdslot);
8831cb0ef41Sopenharmony_ci  bool BranchShortCheck(int32_t offset, Label* L, Condition cond, Register rs,
8841cb0ef41Sopenharmony_ci                        const Operand& rt, BranchDelaySlot bdslot);
8851cb0ef41Sopenharmony_ci
8861cb0ef41Sopenharmony_ci  void BranchAndLinkShortHelperR6(int32_t offset, Label* L);
8871cb0ef41Sopenharmony_ci  void BranchAndLinkShortHelper(int16_t offset, Label* L,
8881cb0ef41Sopenharmony_ci                                BranchDelaySlot bdslot);
8891cb0ef41Sopenharmony_ci  void BranchAndLinkShort(int32_t offset, BranchDelaySlot bdslot = PROTECT);
8901cb0ef41Sopenharmony_ci  void BranchAndLinkShort(Label* L, BranchDelaySlot bdslot = PROTECT);
8911cb0ef41Sopenharmony_ci  bool BranchAndLinkShortHelperR6(int32_t offset, Label* L, Condition cond,
8921cb0ef41Sopenharmony_ci                                  Register rs, const Operand& rt);
8931cb0ef41Sopenharmony_ci  bool BranchAndLinkShortHelper(int16_t offset, Label* L, Condition cond,
8941cb0ef41Sopenharmony_ci                                Register rs, const Operand& rt,
8951cb0ef41Sopenharmony_ci                                BranchDelaySlot bdslot);
8961cb0ef41Sopenharmony_ci  bool BranchAndLinkShortCheck(int32_t offset, Label* L, Condition cond,
8971cb0ef41Sopenharmony_ci                               Register rs, const Operand& rt,
8981cb0ef41Sopenharmony_ci                               BranchDelaySlot bdslot);
8991cb0ef41Sopenharmony_ci  void BranchAndLinkLong(Label* L, BranchDelaySlot bdslot);
9001cb0ef41Sopenharmony_ci
9011cb0ef41Sopenharmony_ci  template <typename RoundFunc>
9021cb0ef41Sopenharmony_ci  void RoundDouble(FPURegister dst, FPURegister src, FPURoundingMode mode,
9031cb0ef41Sopenharmony_ci                   RoundFunc round);
9041cb0ef41Sopenharmony_ci
9051cb0ef41Sopenharmony_ci  template <typename RoundFunc>
9061cb0ef41Sopenharmony_ci  void RoundFloat(FPURegister dst, FPURegister src, FPURoundingMode mode,
9071cb0ef41Sopenharmony_ci                  RoundFunc round);
9081cb0ef41Sopenharmony_ci
9091cb0ef41Sopenharmony_ci  // Push a fixed frame, consisting of ra, fp.
9101cb0ef41Sopenharmony_ci  void PushCommonFrame(Register marker_reg = no_reg);
9111cb0ef41Sopenharmony_ci};
9121cb0ef41Sopenharmony_ci
9131cb0ef41Sopenharmony_ci// MacroAssembler implements a collection of frequently used macros.
9141cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
9151cb0ef41Sopenharmony_ci public:
9161cb0ef41Sopenharmony_ci  using TurboAssembler::TurboAssembler;
9171cb0ef41Sopenharmony_ci
9181cb0ef41Sopenharmony_ci  // It assumes that the arguments are located below the stack pointer.
9191cb0ef41Sopenharmony_ci  // argc is the number of arguments not including the receiver.
9201cb0ef41Sopenharmony_ci  // TODO(victorgomes): Remove this function once we stick with the reversed
9211cb0ef41Sopenharmony_ci  // arguments order.
9221cb0ef41Sopenharmony_ci  void LoadReceiver(Register dest, Register argc) {
9231cb0ef41Sopenharmony_ci    Lw(dest, MemOperand(sp, 0));
9241cb0ef41Sopenharmony_ci  }
9251cb0ef41Sopenharmony_ci
9261cb0ef41Sopenharmony_ci  void StoreReceiver(Register rec, Register argc, Register scratch) {
9271cb0ef41Sopenharmony_ci    Sw(rec, MemOperand(sp, 0));
9281cb0ef41Sopenharmony_ci  }
9291cb0ef41Sopenharmony_ci
9301cb0ef41Sopenharmony_ci  // Swap two registers.  If the scratch register is omitted then a slightly
9311cb0ef41Sopenharmony_ci  // less efficient form using xor instead of mov is emitted.
9321cb0ef41Sopenharmony_ci  void Swap(Register reg1, Register reg2, Register scratch = no_reg);
9331cb0ef41Sopenharmony_ci
9341cb0ef41Sopenharmony_ci  void PushRoot(RootIndex index) {
9351cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
9361cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
9371cb0ef41Sopenharmony_ci    LoadRoot(scratch, index);
9381cb0ef41Sopenharmony_ci    Push(scratch);
9391cb0ef41Sopenharmony_ci  }
9401cb0ef41Sopenharmony_ci
9411cb0ef41Sopenharmony_ci  // Compare the object in a register to a value and jump if they are equal.
9421cb0ef41Sopenharmony_ci  void JumpIfRoot(Register with, RootIndex index, Label* if_equal) {
9431cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
9441cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
9451cb0ef41Sopenharmony_ci    LoadRoot(scratch, index);
9461cb0ef41Sopenharmony_ci    Branch(if_equal, eq, with, Operand(scratch));
9471cb0ef41Sopenharmony_ci  }
9481cb0ef41Sopenharmony_ci
9491cb0ef41Sopenharmony_ci  // Compare the object in a register to a value and jump if they are not equal.
9501cb0ef41Sopenharmony_ci  void JumpIfNotRoot(Register with, RootIndex index, Label* if_not_equal) {
9511cb0ef41Sopenharmony_ci    UseScratchRegisterScope temps(this);
9521cb0ef41Sopenharmony_ci    Register scratch = temps.Acquire();
9531cb0ef41Sopenharmony_ci    LoadRoot(scratch, index);
9541cb0ef41Sopenharmony_ci    Branch(if_not_equal, ne, with, Operand(scratch));
9551cb0ef41Sopenharmony_ci  }
9561cb0ef41Sopenharmony_ci
9571cb0ef41Sopenharmony_ci  // Checks if value is in range [lower_limit, higher_limit] using a single
9581cb0ef41Sopenharmony_ci  // comparison.
9591cb0ef41Sopenharmony_ci  void JumpIfIsInRange(Register value, unsigned lower_limit,
9601cb0ef41Sopenharmony_ci                       unsigned higher_limit, Label* on_in_range);
9611cb0ef41Sopenharmony_ci
9621cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
9631cb0ef41Sopenharmony_ci  // GC Support
9641cb0ef41Sopenharmony_ci
9651cb0ef41Sopenharmony_ci  // Notify the garbage collector that we wrote a pointer into an object.
9661cb0ef41Sopenharmony_ci  // |object| is the object being stored into, |value| is the object being
9671cb0ef41Sopenharmony_ci  // stored.  value and scratch registers are clobbered by the operation.
9681cb0ef41Sopenharmony_ci  // The offset is the offset from the start of the object, not the offset from
9691cb0ef41Sopenharmony_ci  // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
9701cb0ef41Sopenharmony_ci  void RecordWriteField(
9711cb0ef41Sopenharmony_ci      Register object, int offset, Register value, Register scratch,
9721cb0ef41Sopenharmony_ci      RAStatus ra_status, SaveFPRegsMode save_fp,
9731cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action = RememberedSetAction::kEmit,
9741cb0ef41Sopenharmony_ci      SmiCheck smi_check = SmiCheck::kInline);
9751cb0ef41Sopenharmony_ci
9761cb0ef41Sopenharmony_ci  // For a given |object| notify the garbage collector that the slot |address|
9771cb0ef41Sopenharmony_ci  // has been written.  |value| is the object being stored. The value and
9781cb0ef41Sopenharmony_ci  // address registers are clobbered by the operation.
9791cb0ef41Sopenharmony_ci  void RecordWrite(
9801cb0ef41Sopenharmony_ci      Register object, Register address, Register value, RAStatus ra_status,
9811cb0ef41Sopenharmony_ci      SaveFPRegsMode save_fp,
9821cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action = RememberedSetAction::kEmit,
9831cb0ef41Sopenharmony_ci      SmiCheck smi_check = SmiCheck::kInline);
9841cb0ef41Sopenharmony_ci
9851cb0ef41Sopenharmony_ci  void Pref(int32_t hint, const MemOperand& rs);
9861cb0ef41Sopenharmony_ci
9871cb0ef41Sopenharmony_ci  // Enter exit frame.
9881cb0ef41Sopenharmony_ci  // argc - argument count to be dropped by LeaveExitFrame.
9891cb0ef41Sopenharmony_ci  // save_doubles - saves FPU registers on stack, currently disabled.
9901cb0ef41Sopenharmony_ci  // stack_space - extra stack space.
9911cb0ef41Sopenharmony_ci  void EnterExitFrame(bool save_doubles, int stack_space = 0,
9921cb0ef41Sopenharmony_ci                      StackFrame::Type frame_type = StackFrame::EXIT);
9931cb0ef41Sopenharmony_ci
9941cb0ef41Sopenharmony_ci  // Leave the current exit frame.
9951cb0ef41Sopenharmony_ci  void LeaveExitFrame(bool save_doubles, Register arg_count,
9961cb0ef41Sopenharmony_ci                      bool do_return = NO_EMIT_RETURN,
9971cb0ef41Sopenharmony_ci                      bool argument_count_is_length = false);
9981cb0ef41Sopenharmony_ci
9991cb0ef41Sopenharmony_ci  // Make sure the stack is aligned. Only emits code in debug mode.
10001cb0ef41Sopenharmony_ci  void AssertStackIsAligned();
10011cb0ef41Sopenharmony_ci
10021cb0ef41Sopenharmony_ci  // Load the global proxy from the current context.
10031cb0ef41Sopenharmony_ci  void LoadGlobalProxy(Register dst) {
10041cb0ef41Sopenharmony_ci    LoadNativeContextSlot(dst, Context::GLOBAL_PROXY_INDEX);
10051cb0ef41Sopenharmony_ci  }
10061cb0ef41Sopenharmony_ci
10071cb0ef41Sopenharmony_ci  void LoadNativeContextSlot(Register dst, int index);
10081cb0ef41Sopenharmony_ci
10091cb0ef41Sopenharmony_ci  // -------------------------------------------------------------------------
10101cb0ef41Sopenharmony_ci  // JavaScript invokes.
10111cb0ef41Sopenharmony_ci
10121cb0ef41Sopenharmony_ci  // Invoke the JavaScript function code by either calling or jumping.
10131cb0ef41Sopenharmony_ci  void InvokeFunctionCode(Register function, Register new_target,
10141cb0ef41Sopenharmony_ci                          Register expected_parameter_count,
10151cb0ef41Sopenharmony_ci                          Register actual_parameter_count, InvokeType type);
10161cb0ef41Sopenharmony_ci
10171cb0ef41Sopenharmony_ci  // On function call, call into the debugger if necessary.
10181cb0ef41Sopenharmony_ci  void CheckDebugHook(Register fun, Register new_target,
10191cb0ef41Sopenharmony_ci                      Register expected_parameter_count,
10201cb0ef41Sopenharmony_ci                      Register actual_parameter_count);
10211cb0ef41Sopenharmony_ci
10221cb0ef41Sopenharmony_ci  // Invoke the JavaScript function in the given register. Changes the
10231cb0ef41Sopenharmony_ci  // current context to the context in the function before invoking.
10241cb0ef41Sopenharmony_ci  void InvokeFunctionWithNewTarget(Register function, Register new_target,
10251cb0ef41Sopenharmony_ci                                   Register actual_parameter_count,
10261cb0ef41Sopenharmony_ci                                   InvokeType type);
10271cb0ef41Sopenharmony_ci
10281cb0ef41Sopenharmony_ci  void InvokeFunction(Register function, Register expected_parameter_count,
10291cb0ef41Sopenharmony_ci                      Register actual_parameter_count, InvokeType type);
10301cb0ef41Sopenharmony_ci
10311cb0ef41Sopenharmony_ci  // Exception handling.
10321cb0ef41Sopenharmony_ci
10331cb0ef41Sopenharmony_ci  // Push a new stack handler and link into stack handler chain.
10341cb0ef41Sopenharmony_ci  void PushStackHandler();
10351cb0ef41Sopenharmony_ci
10361cb0ef41Sopenharmony_ci  // Unlink the stack handler on top of the stack from the stack handler chain.
10371cb0ef41Sopenharmony_ci  // Must preserve the result register.
10381cb0ef41Sopenharmony_ci  void PopStackHandler();
10391cb0ef41Sopenharmony_ci
10401cb0ef41Sopenharmony_ci  // -------------------------------------------------------------------------
10411cb0ef41Sopenharmony_ci  // Support functions.
10421cb0ef41Sopenharmony_ci
10431cb0ef41Sopenharmony_ci  void GetObjectType(Register function, Register map, Register type_reg);
10441cb0ef41Sopenharmony_ci
10451cb0ef41Sopenharmony_ci  void GetInstanceTypeRange(Register map, Register type_reg,
10461cb0ef41Sopenharmony_ci                            InstanceType lower_limit, Register range);
10471cb0ef41Sopenharmony_ci
10481cb0ef41Sopenharmony_ci  // -------------------------------------------------------------------------
10491cb0ef41Sopenharmony_ci  // Runtime calls.
10501cb0ef41Sopenharmony_ci
10511cb0ef41Sopenharmony_ci  // Call a runtime routine.
10521cb0ef41Sopenharmony_ci  void CallRuntime(const Runtime::Function* f, int num_arguments,
10531cb0ef41Sopenharmony_ci                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore);
10541cb0ef41Sopenharmony_ci
10551cb0ef41Sopenharmony_ci  // Convenience function: Same as above, but takes the fid instead.
10561cb0ef41Sopenharmony_ci  void CallRuntime(Runtime::FunctionId fid,
10571cb0ef41Sopenharmony_ci                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) {
10581cb0ef41Sopenharmony_ci    const Runtime::Function* function = Runtime::FunctionForId(fid);
10591cb0ef41Sopenharmony_ci    CallRuntime(function, function->nargs, save_doubles);
10601cb0ef41Sopenharmony_ci  }
10611cb0ef41Sopenharmony_ci
10621cb0ef41Sopenharmony_ci  // Convenience function: Same as above, but takes the fid instead.
10631cb0ef41Sopenharmony_ci  void CallRuntime(Runtime::FunctionId id, int num_arguments,
10641cb0ef41Sopenharmony_ci                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) {
10651cb0ef41Sopenharmony_ci    CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles);
10661cb0ef41Sopenharmony_ci  }
10671cb0ef41Sopenharmony_ci
10681cb0ef41Sopenharmony_ci  // Convenience function: tail call a runtime routine (jump).
10691cb0ef41Sopenharmony_ci  void TailCallRuntime(Runtime::FunctionId fid);
10701cb0ef41Sopenharmony_ci
10711cb0ef41Sopenharmony_ci  // Jump to the builtin routine.
10721cb0ef41Sopenharmony_ci  void JumpToExternalReference(const ExternalReference& builtin,
10731cb0ef41Sopenharmony_ci                               BranchDelaySlot bd = PROTECT,
10741cb0ef41Sopenharmony_ci                               bool builtin_exit_frame = false);
10751cb0ef41Sopenharmony_ci
10761cb0ef41Sopenharmony_ci  // Generates a trampoline to jump to the off-heap instruction stream.
10771cb0ef41Sopenharmony_ci  void JumpToOffHeapInstructionStream(Address entry);
10781cb0ef41Sopenharmony_ci
10791cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
10801cb0ef41Sopenharmony_ci  // In-place weak references.
10811cb0ef41Sopenharmony_ci  void LoadWeakValue(Register out, Register in, Label* target_if_cleared);
10821cb0ef41Sopenharmony_ci
10831cb0ef41Sopenharmony_ci  // -------------------------------------------------------------------------
10841cb0ef41Sopenharmony_ci  // StatsCounter support.
10851cb0ef41Sopenharmony_ci
10861cb0ef41Sopenharmony_ci  void IncrementCounter(StatsCounter* counter, int value, Register scratch1,
10871cb0ef41Sopenharmony_ci                        Register scratch2) {
10881cb0ef41Sopenharmony_ci    if (!FLAG_native_code_counters) return;
10891cb0ef41Sopenharmony_ci    EmitIncrementCounter(counter, value, scratch1, scratch2);
10901cb0ef41Sopenharmony_ci  }
10911cb0ef41Sopenharmony_ci  void EmitIncrementCounter(StatsCounter* counter, int value, Register scratch1,
10921cb0ef41Sopenharmony_ci                            Register scratch2);
10931cb0ef41Sopenharmony_ci  void DecrementCounter(StatsCounter* counter, int value, Register scratch1,
10941cb0ef41Sopenharmony_ci                        Register scratch2) {
10951cb0ef41Sopenharmony_ci    if (!FLAG_native_code_counters) return;
10961cb0ef41Sopenharmony_ci    EmitDecrementCounter(counter, value, scratch1, scratch2);
10971cb0ef41Sopenharmony_ci  }
10981cb0ef41Sopenharmony_ci  void EmitDecrementCounter(StatsCounter* counter, int value, Register scratch1,
10991cb0ef41Sopenharmony_ci                            Register scratch2);
11001cb0ef41Sopenharmony_ci
11011cb0ef41Sopenharmony_ci  // -------------------------------------------------------------------------
11021cb0ef41Sopenharmony_ci  // Stack limit utilities
11031cb0ef41Sopenharmony_ci
11041cb0ef41Sopenharmony_ci  enum StackLimitKind { kInterruptStackLimit, kRealStackLimit };
11051cb0ef41Sopenharmony_ci  void LoadStackLimit(Register destination, StackLimitKind kind);
11061cb0ef41Sopenharmony_ci  void StackOverflowCheck(Register num_args, Register scratch1,
11071cb0ef41Sopenharmony_ci                          Register scratch2, Label* stack_overflow);
11081cb0ef41Sopenharmony_ci
11091cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
11101cb0ef41Sopenharmony_ci  // Smi utilities.
11111cb0ef41Sopenharmony_ci
11121cb0ef41Sopenharmony_ci  void SmiTag(Register reg) { Addu(reg, reg, reg); }
11131cb0ef41Sopenharmony_ci
11141cb0ef41Sopenharmony_ci  void SmiTag(Register dst, Register src) { Addu(dst, src, src); }
11151cb0ef41Sopenharmony_ci
11161cb0ef41Sopenharmony_ci  // Test if the register contains a smi.
11171cb0ef41Sopenharmony_ci  inline void SmiTst(Register value, Register scratch) {
11181cb0ef41Sopenharmony_ci    And(scratch, value, Operand(kSmiTagMask));
11191cb0ef41Sopenharmony_ci  }
11201cb0ef41Sopenharmony_ci
11211cb0ef41Sopenharmony_ci  // Jump if the register contains a non-smi.
11221cb0ef41Sopenharmony_ci  void JumpIfNotSmi(Register value, Label* not_smi_label,
11231cb0ef41Sopenharmony_ci                    BranchDelaySlot bd = PROTECT);
11241cb0ef41Sopenharmony_ci
11251cb0ef41Sopenharmony_ci  // Abort execution if argument is a smi, enabled via --debug-code.
11261cb0ef41Sopenharmony_ci  void AssertNotSmi(Register object);
11271cb0ef41Sopenharmony_ci  void AssertSmi(Register object);
11281cb0ef41Sopenharmony_ci
11291cb0ef41Sopenharmony_ci  // Abort execution if argument is not a Constructor, enabled via --debug-code.
11301cb0ef41Sopenharmony_ci  void AssertConstructor(Register object);
11311cb0ef41Sopenharmony_ci
11321cb0ef41Sopenharmony_ci  // Abort execution if argument is not a JSFunction, enabled via --debug-code.
11331cb0ef41Sopenharmony_ci  void AssertFunction(Register object);
11341cb0ef41Sopenharmony_ci
11351cb0ef41Sopenharmony_ci  // Abort execution if argument is not a callable JSFunction, enabled via
11361cb0ef41Sopenharmony_ci  // --debug-code.
11371cb0ef41Sopenharmony_ci  void AssertCallableFunction(Register object);
11381cb0ef41Sopenharmony_ci
11391cb0ef41Sopenharmony_ci  // Abort execution if argument is not a JSBoundFunction,
11401cb0ef41Sopenharmony_ci  // enabled via --debug-code.
11411cb0ef41Sopenharmony_ci  void AssertBoundFunction(Register object);
11421cb0ef41Sopenharmony_ci
11431cb0ef41Sopenharmony_ci  // Abort execution if argument is not a JSGeneratorObject (or subclass),
11441cb0ef41Sopenharmony_ci  // enabled via --debug-code.
11451cb0ef41Sopenharmony_ci  void AssertGeneratorObject(Register object);
11461cb0ef41Sopenharmony_ci
11471cb0ef41Sopenharmony_ci  // Abort execution if argument is not undefined or an AllocationSite, enabled
11481cb0ef41Sopenharmony_ci  // via --debug-code.
11491cb0ef41Sopenharmony_ci  void AssertUndefinedOrAllocationSite(Register object, Register scratch);
11501cb0ef41Sopenharmony_ci
11511cb0ef41Sopenharmony_ci  template <typename Field>
11521cb0ef41Sopenharmony_ci  void DecodeField(Register dst, Register src) {
11531cb0ef41Sopenharmony_ci    Ext(dst, src, Field::kShift, Field::kSize);
11541cb0ef41Sopenharmony_ci  }
11551cb0ef41Sopenharmony_ci
11561cb0ef41Sopenharmony_ci  template <typename Field>
11571cb0ef41Sopenharmony_ci  void DecodeField(Register reg) {
11581cb0ef41Sopenharmony_ci    DecodeField<Field>(reg, reg);
11591cb0ef41Sopenharmony_ci  }
11601cb0ef41Sopenharmony_ci
11611cb0ef41Sopenharmony_ci private:
11621cb0ef41Sopenharmony_ci  // Helper functions for generating invokes.
11631cb0ef41Sopenharmony_ci  void InvokePrologue(Register expected_parameter_count,
11641cb0ef41Sopenharmony_ci                      Register actual_parameter_count, Label* done,
11651cb0ef41Sopenharmony_ci                      InvokeType type);
11661cb0ef41Sopenharmony_ci
11671cb0ef41Sopenharmony_ci  DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
11681cb0ef41Sopenharmony_ci};
11691cb0ef41Sopenharmony_ci
11701cb0ef41Sopenharmony_citemplate <typename Func>
11711cb0ef41Sopenharmony_civoid TurboAssembler::GenerateSwitchTable(Register index, size_t case_count,
11721cb0ef41Sopenharmony_ci                                         Func GetLabelFunction) {
11731cb0ef41Sopenharmony_ci  Label here;
11741cb0ef41Sopenharmony_ci  BlockTrampolinePoolFor(case_count + kSwitchTablePrologueSize);
11751cb0ef41Sopenharmony_ci  UseScratchRegisterScope temps(this);
11761cb0ef41Sopenharmony_ci  Register scratch = temps.Acquire();
11771cb0ef41Sopenharmony_ci  if (kArchVariant >= kMips32r6) {
11781cb0ef41Sopenharmony_ci    addiupc(scratch, 5);
11791cb0ef41Sopenharmony_ci    Lsa(scratch, scratch, index, kPointerSizeLog2);
11801cb0ef41Sopenharmony_ci    lw(scratch, MemOperand(scratch));
11811cb0ef41Sopenharmony_ci  } else {
11821cb0ef41Sopenharmony_ci    push(ra);
11831cb0ef41Sopenharmony_ci    bal(&here);
11841cb0ef41Sopenharmony_ci    sll(scratch, index, kPointerSizeLog2);  // Branch delay slot.
11851cb0ef41Sopenharmony_ci    bind(&here);
11861cb0ef41Sopenharmony_ci    addu(scratch, scratch, ra);
11871cb0ef41Sopenharmony_ci    pop(ra);
11881cb0ef41Sopenharmony_ci    lw(scratch, MemOperand(scratch, 6 * v8::internal::kInstrSize));
11891cb0ef41Sopenharmony_ci  }
11901cb0ef41Sopenharmony_ci  jr(scratch);
11911cb0ef41Sopenharmony_ci  nop();  // Branch delay slot nop.
11921cb0ef41Sopenharmony_ci  for (size_t index = 0; index < case_count; ++index) {
11931cb0ef41Sopenharmony_ci    dd(GetLabelFunction(index));
11941cb0ef41Sopenharmony_ci  }
11951cb0ef41Sopenharmony_ci}
11961cb0ef41Sopenharmony_ci
11971cb0ef41Sopenharmony_ci#define ACCESS_MASM(masm) masm->
11981cb0ef41Sopenharmony_ci
11991cb0ef41Sopenharmony_ci}  // namespace internal
12001cb0ef41Sopenharmony_ci}  // namespace v8
12011cb0ef41Sopenharmony_ci
12021cb0ef41Sopenharmony_ci#endif  // V8_CODEGEN_MIPS_MACRO_ASSEMBLER_MIPS_H_
1203