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