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_IA32_MACRO_ASSEMBLER_IA32_H_
101cb0ef41Sopenharmony_ci#define V8_CODEGEN_IA32_MACRO_ASSEMBLER_IA32_H_
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include <stdint.h>
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci#include "include/v8-internal.h"
151cb0ef41Sopenharmony_ci#include "src/base/logging.h"
161cb0ef41Sopenharmony_ci#include "src/base/macros.h"
171cb0ef41Sopenharmony_ci#include "src/builtins/builtins.h"
181cb0ef41Sopenharmony_ci#include "src/codegen/assembler.h"
191cb0ef41Sopenharmony_ci#include "src/codegen/bailout-reason.h"
201cb0ef41Sopenharmony_ci#include "src/codegen/cpu-features.h"
211cb0ef41Sopenharmony_ci#include "src/codegen/ia32/assembler-ia32.h"
221cb0ef41Sopenharmony_ci#include "src/codegen/ia32/register-ia32.h"
231cb0ef41Sopenharmony_ci#include "src/codegen/label.h"
241cb0ef41Sopenharmony_ci#include "src/codegen/reglist.h"
251cb0ef41Sopenharmony_ci#include "src/codegen/reloc-info.h"
261cb0ef41Sopenharmony_ci#include "src/codegen/shared-ia32-x64/macro-assembler-shared-ia32-x64.h"
271cb0ef41Sopenharmony_ci#include "src/codegen/turbo-assembler.h"
281cb0ef41Sopenharmony_ci#include "src/common/globals.h"
291cb0ef41Sopenharmony_ci#include "src/execution/frames.h"
301cb0ef41Sopenharmony_ci#include "src/handles/handles.h"
311cb0ef41Sopenharmony_ci#include "src/objects/heap-object.h"
321cb0ef41Sopenharmony_ci#include "src/objects/smi.h"
331cb0ef41Sopenharmony_ci#include "src/roots/roots.h"
341cb0ef41Sopenharmony_ci#include "src/runtime/runtime.h"
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_cinamespace v8 {
371cb0ef41Sopenharmony_cinamespace internal {
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ciclass Code;
401cb0ef41Sopenharmony_ciclass ExternalReference;
411cb0ef41Sopenharmony_ciclass StatsCounter;
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci// Convenience for platform-independent signatures.  We do not normally
441cb0ef41Sopenharmony_ci// distinguish memory operands from other operands on ia32.
451cb0ef41Sopenharmony_ciusing MemOperand = Operand;
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci// TODO(victorgomes): Move definition to macro-assembler.h, once all other
481cb0ef41Sopenharmony_ci// platforms are updated.
491cb0ef41Sopenharmony_cienum class StackLimitKind { kInterruptStackLimit, kRealStackLimit };
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci// Convenient class to access arguments below the stack pointer.
521cb0ef41Sopenharmony_ciclass StackArgumentsAccessor {
531cb0ef41Sopenharmony_ci public:
541cb0ef41Sopenharmony_ci  // argc = the number of arguments not including the receiver.
551cb0ef41Sopenharmony_ci  explicit StackArgumentsAccessor(Register argc) : argc_(argc) {
561cb0ef41Sopenharmony_ci    DCHECK_NE(argc_, no_reg);
571cb0ef41Sopenharmony_ci  }
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  // Argument 0 is the receiver (despite argc not including the receiver).
601cb0ef41Sopenharmony_ci  Operand operator[](int index) const { return GetArgumentOperand(index); }
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  Operand GetArgumentOperand(int index) const;
631cb0ef41Sopenharmony_ci  Operand GetReceiverOperand() const { return GetArgumentOperand(0); }
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci private:
661cb0ef41Sopenharmony_ci  const Register argc_;
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  DISALLOW_IMPLICIT_CONSTRUCTORS(StackArgumentsAccessor);
691cb0ef41Sopenharmony_ci};
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE TurboAssembler
721cb0ef41Sopenharmony_ci    : public SharedTurboAssemblerBase<TurboAssembler> {
731cb0ef41Sopenharmony_ci public:
741cb0ef41Sopenharmony_ci  using SharedTurboAssemblerBase<TurboAssembler>::SharedTurboAssemblerBase;
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  void CheckPageFlag(Register object, Register scratch, int mask, Condition cc,
771cb0ef41Sopenharmony_ci                     Label* condition_met,
781cb0ef41Sopenharmony_ci                     Label::Distance condition_met_distance = Label::kFar);
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  // Activation support.
811cb0ef41Sopenharmony_ci  void EnterFrame(StackFrame::Type type);
821cb0ef41Sopenharmony_ci  void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg) {
831cb0ef41Sopenharmony_ci    // Out-of-line constant pool not implemented on ia32.
841cb0ef41Sopenharmony_ci    UNREACHABLE();
851cb0ef41Sopenharmony_ci  }
861cb0ef41Sopenharmony_ci  void LeaveFrame(StackFrame::Type type);
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci// Allocate stack space of given size (i.e. decrement {esp} by the value
891cb0ef41Sopenharmony_ci// stored in the given register, or by a constant). If you need to perform a
901cb0ef41Sopenharmony_ci// stack check, do it before calling this function because this function may
911cb0ef41Sopenharmony_ci// write into the newly allocated space. It may also overwrite the given
921cb0ef41Sopenharmony_ci// register's value, in the version that takes a register.
931cb0ef41Sopenharmony_ci#ifdef V8_OS_WIN
941cb0ef41Sopenharmony_ci  void AllocateStackSpace(Register bytes_scratch);
951cb0ef41Sopenharmony_ci  void AllocateStackSpace(int bytes);
961cb0ef41Sopenharmony_ci#else
971cb0ef41Sopenharmony_ci  void AllocateStackSpace(Register bytes) { sub(esp, bytes); }
981cb0ef41Sopenharmony_ci  void AllocateStackSpace(int bytes) {
991cb0ef41Sopenharmony_ci    DCHECK_GE(bytes, 0);
1001cb0ef41Sopenharmony_ci    if (bytes == 0) return;
1011cb0ef41Sopenharmony_ci    sub(esp, Immediate(bytes));
1021cb0ef41Sopenharmony_ci  }
1031cb0ef41Sopenharmony_ci#endif
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  // Print a message to stdout and abort execution.
1061cb0ef41Sopenharmony_ci  void Abort(AbortReason reason);
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  // Calls Abort(msg) if the condition cc is not satisfied.
1091cb0ef41Sopenharmony_ci  // Use --debug_code to enable.
1101cb0ef41Sopenharmony_ci  void Assert(Condition cc, AbortReason reason);
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  // Like Assert(), but without condition.
1131cb0ef41Sopenharmony_ci  // Use --debug_code to enable.
1141cb0ef41Sopenharmony_ci  void AssertUnreachable(AbortReason reason);
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci  // Like Assert(), but always enabled.
1171cb0ef41Sopenharmony_ci  void Check(Condition cc, AbortReason reason);
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  // Check that the stack is aligned.
1201cb0ef41Sopenharmony_ci  void CheckStackAlignment();
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci  // Move a constant into a destination using the most efficient encoding.
1231cb0ef41Sopenharmony_ci  void Move(Register dst, int32_t x) {
1241cb0ef41Sopenharmony_ci    if (x == 0) {
1251cb0ef41Sopenharmony_ci      xor_(dst, dst);
1261cb0ef41Sopenharmony_ci    } else {
1271cb0ef41Sopenharmony_ci      mov(dst, Immediate(x));
1281cb0ef41Sopenharmony_ci    }
1291cb0ef41Sopenharmony_ci  }
1301cb0ef41Sopenharmony_ci  void Move(Register dst, const Immediate& src);
1311cb0ef41Sopenharmony_ci  void Move(Register dst, Smi src) { Move(dst, Immediate(src)); }
1321cb0ef41Sopenharmony_ci  void Move(Register dst, Handle<HeapObject> src);
1331cb0ef41Sopenharmony_ci  void Move(Register dst, Register src);
1341cb0ef41Sopenharmony_ci  void Move(Register dst, Operand src);
1351cb0ef41Sopenharmony_ci  void Move(Operand dst, const Immediate& src);
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  // Move an immediate into an XMM register.
1381cb0ef41Sopenharmony_ci  void Move(XMMRegister dst, uint32_t src);
1391cb0ef41Sopenharmony_ci  void Move(XMMRegister dst, uint64_t src);
1401cb0ef41Sopenharmony_ci  void Move(XMMRegister dst, float src) { Move(dst, bit_cast<uint32_t>(src)); }
1411cb0ef41Sopenharmony_ci  void Move(XMMRegister dst, double src) { Move(dst, bit_cast<uint64_t>(src)); }
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  Operand EntryFromBuiltinAsOperand(Builtin builtin);
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  void Call(Register reg) { call(reg); }
1461cb0ef41Sopenharmony_ci  void Call(Operand op) { call(op); }
1471cb0ef41Sopenharmony_ci  void Call(Label* target) { call(target); }
1481cb0ef41Sopenharmony_ci  void Call(Handle<Code> code_object, RelocInfo::Mode rmode);
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  // Load the builtin given by the Smi in |builtin_index| into the same
1511cb0ef41Sopenharmony_ci  // register.
1521cb0ef41Sopenharmony_ci  void LoadEntryFromBuiltinIndex(Register builtin_index);
1531cb0ef41Sopenharmony_ci  void CallBuiltinByIndex(Register builtin_index);
1541cb0ef41Sopenharmony_ci  void CallBuiltin(Builtin builtin);
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci  void LoadCodeObjectEntry(Register destination, Register code_object);
1571cb0ef41Sopenharmony_ci  void CallCodeObject(Register code_object);
1581cb0ef41Sopenharmony_ci  void JumpCodeObject(Register code_object,
1591cb0ef41Sopenharmony_ci                      JumpMode jump_mode = JumpMode::kJump);
1601cb0ef41Sopenharmony_ci  void Jump(const ExternalReference& reference);
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  void Jump(Handle<Code> code_object, RelocInfo::Mode rmode);
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  void LoadMap(Register destination, Register object);
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  void Trap();
1671cb0ef41Sopenharmony_ci  void DebugBreak();
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  void CallForDeoptimization(Builtin target, int deopt_id, Label* exit,
1701cb0ef41Sopenharmony_ci                             DeoptimizeKind kind, Label* ret,
1711cb0ef41Sopenharmony_ci                             Label* jump_deoptimization_entry_label);
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci  // Jump the register contains a smi.
1741cb0ef41Sopenharmony_ci  inline void JumpIfSmi(Register value, Label* smi_label,
1751cb0ef41Sopenharmony_ci                        Label::Distance distance = Label::kFar) {
1761cb0ef41Sopenharmony_ci    test(value, Immediate(kSmiTagMask));
1771cb0ef41Sopenharmony_ci    j(zero, smi_label, distance);
1781cb0ef41Sopenharmony_ci  }
1791cb0ef41Sopenharmony_ci  // Jump if the operand is a smi.
1801cb0ef41Sopenharmony_ci  inline void JumpIfSmi(Operand value, Label* smi_label,
1811cb0ef41Sopenharmony_ci                        Label::Distance distance = Label::kFar) {
1821cb0ef41Sopenharmony_ci    test(value, Immediate(kSmiTagMask));
1831cb0ef41Sopenharmony_ci    j(zero, smi_label, distance);
1841cb0ef41Sopenharmony_ci  }
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci  void JumpIfEqual(Register a, int32_t b, Label* dest) {
1871cb0ef41Sopenharmony_ci    cmp(a, Immediate(b));
1881cb0ef41Sopenharmony_ci    j(equal, dest);
1891cb0ef41Sopenharmony_ci  }
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci  void JumpIfLessThan(Register a, int32_t b, Label* dest) {
1921cb0ef41Sopenharmony_ci    cmp(a, Immediate(b));
1931cb0ef41Sopenharmony_ci    j(less, dest);
1941cb0ef41Sopenharmony_ci  }
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  void SmiUntag(Register reg) { sar(reg, kSmiTagSize); }
1971cb0ef41Sopenharmony_ci  void SmiUntag(Register output, Register value) {
1981cb0ef41Sopenharmony_ci    mov(output, value);
1991cb0ef41Sopenharmony_ci    SmiUntag(output);
2001cb0ef41Sopenharmony_ci  }
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci  void SmiToInt32(Register reg) { SmiUntag(reg); }
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci  // Before calling a C-function from generated code, align arguments on stack.
2051cb0ef41Sopenharmony_ci  // After aligning the frame, arguments must be stored in esp[0], esp[4],
2061cb0ef41Sopenharmony_ci  // etc., not pushed. The argument count assumes all arguments are word sized.
2071cb0ef41Sopenharmony_ci  // Some compilers/platforms require the stack to be aligned when calling
2081cb0ef41Sopenharmony_ci  // C++ code.
2091cb0ef41Sopenharmony_ci  // Needs a scratch register to do some arithmetic. This register will be
2101cb0ef41Sopenharmony_ci  // trashed.
2111cb0ef41Sopenharmony_ci  void PrepareCallCFunction(int num_arguments, Register scratch);
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci  // Calls a C function and cleans up the space for arguments allocated
2141cb0ef41Sopenharmony_ci  // by PrepareCallCFunction. The called function is not allowed to trigger a
2151cb0ef41Sopenharmony_ci  // garbage collection, since that might move the code and invalidate the
2161cb0ef41Sopenharmony_ci  // return address (unless this is somehow accounted for by the called
2171cb0ef41Sopenharmony_ci  // function).
2181cb0ef41Sopenharmony_ci  void CallCFunction(ExternalReference function, int num_arguments);
2191cb0ef41Sopenharmony_ci  void CallCFunction(Register function, int num_arguments);
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci  void ShlPair(Register high, Register low, uint8_t imm8);
2221cb0ef41Sopenharmony_ci  void ShlPair_cl(Register high, Register low);
2231cb0ef41Sopenharmony_ci  void ShrPair(Register high, Register low, uint8_t imm8);
2241cb0ef41Sopenharmony_ci  void ShrPair_cl(Register high, Register low);
2251cb0ef41Sopenharmony_ci  void SarPair(Register high, Register low, uint8_t imm8);
2261cb0ef41Sopenharmony_ci  void SarPair_cl(Register high, Register low);
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ci  // Generates function and stub prologue code.
2291cb0ef41Sopenharmony_ci  void StubPrologue(StackFrame::Type type);
2301cb0ef41Sopenharmony_ci  void Prologue();
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci  // Helpers for argument handling
2331cb0ef41Sopenharmony_ci  enum ArgumentsCountMode { kCountIncludesReceiver, kCountExcludesReceiver };
2341cb0ef41Sopenharmony_ci  enum ArgumentsCountType { kCountIsInteger, kCountIsSmi, kCountIsBytes };
2351cb0ef41Sopenharmony_ci  void DropArguments(Register count, Register scratch, ArgumentsCountType type,
2361cb0ef41Sopenharmony_ci                     ArgumentsCountMode mode);
2371cb0ef41Sopenharmony_ci  void DropArgumentsAndPushNewReceiver(Register argc, Register receiver,
2381cb0ef41Sopenharmony_ci                                       Register scratch,
2391cb0ef41Sopenharmony_ci                                       ArgumentsCountType type,
2401cb0ef41Sopenharmony_ci                                       ArgumentsCountMode mode);
2411cb0ef41Sopenharmony_ci  void DropArgumentsAndPushNewReceiver(Register argc, Operand receiver,
2421cb0ef41Sopenharmony_ci                                       Register scratch,
2431cb0ef41Sopenharmony_ci                                       ArgumentsCountType type,
2441cb0ef41Sopenharmony_ci                                       ArgumentsCountMode mode);
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci  void Lzcnt(Register dst, Register src) { Lzcnt(dst, Operand(src)); }
2471cb0ef41Sopenharmony_ci  void Lzcnt(Register dst, Operand src);
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_ci  void Tzcnt(Register dst, Register src) { Tzcnt(dst, Operand(src)); }
2501cb0ef41Sopenharmony_ci  void Tzcnt(Register dst, Operand src);
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci  void Popcnt(Register dst, Register src) { Popcnt(dst, Operand(src)); }
2531cb0ef41Sopenharmony_ci  void Popcnt(Register dst, Operand src);
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci  void PushReturnAddressFrom(Register src) { push(src); }
2561cb0ef41Sopenharmony_ci  void PopReturnAddressTo(Register dst) { pop(dst); }
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci  void PushReturnAddressFrom(XMMRegister src, Register scratch) {
2591cb0ef41Sopenharmony_ci    Push(src, scratch);
2601cb0ef41Sopenharmony_ci  }
2611cb0ef41Sopenharmony_ci  void PopReturnAddressTo(XMMRegister dst, Register scratch) {
2621cb0ef41Sopenharmony_ci    Pop(dst, scratch);
2631cb0ef41Sopenharmony_ci  }
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_ci  void Ret();
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci  // Root register utility functions.
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci  void InitializeRootRegister();
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci  Operand RootAsOperand(RootIndex index);
2721cb0ef41Sopenharmony_ci  void LoadRoot(Register destination, RootIndex index) final;
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci  // Indirect root-relative loads.
2751cb0ef41Sopenharmony_ci  void LoadFromConstantsTable(Register destination, int constant_index) final;
2761cb0ef41Sopenharmony_ci  void LoadRootRegisterOffset(Register destination, intptr_t offset) final;
2771cb0ef41Sopenharmony_ci  void LoadRootRelative(Register destination, int32_t offset) final;
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci  void PushPC();
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci  enum class PushArrayOrder { kNormal, kReverse };
2821cb0ef41Sopenharmony_ci  // `array` points to the first element (the lowest address).
2831cb0ef41Sopenharmony_ci  // `array` and `size` are not modified.
2841cb0ef41Sopenharmony_ci  void PushArray(Register array, Register size, Register scratch,
2851cb0ef41Sopenharmony_ci                 PushArrayOrder order = PushArrayOrder::kNormal);
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci  // Operand pointing to an external reference.
2881cb0ef41Sopenharmony_ci  // May emit code to set up the scratch register. The operand is
2891cb0ef41Sopenharmony_ci  // only guaranteed to be correct as long as the scratch register
2901cb0ef41Sopenharmony_ci  // isn't changed.
2911cb0ef41Sopenharmony_ci  // If the operand is used more than once, use a scratch register
2921cb0ef41Sopenharmony_ci  // that is guaranteed not to be clobbered.
2931cb0ef41Sopenharmony_ci  Operand ExternalReferenceAsOperand(ExternalReference reference,
2941cb0ef41Sopenharmony_ci                                     Register scratch);
2951cb0ef41Sopenharmony_ci  Operand ExternalReferenceAddressAsOperand(ExternalReference reference);
2961cb0ef41Sopenharmony_ci  Operand HeapObjectAsOperand(Handle<HeapObject> object);
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci  void LoadAddress(Register destination, ExternalReference source);
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci  void CompareRoot(Register with, RootIndex index);
3011cb0ef41Sopenharmony_ci  void CompareRoot(Register with, Register scratch, RootIndex index);
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci  // Return and drop arguments from stack, where the number of arguments
3041cb0ef41Sopenharmony_ci  // may be bigger than 2^16 - 1.  Requires a scratch register.
3051cb0ef41Sopenharmony_ci  void Ret(int bytes_dropped, Register scratch);
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci  void PextrdPreSse41(Register dst, XMMRegister src, uint8_t imm8);
3081cb0ef41Sopenharmony_ci  void PinsrdPreSse41(XMMRegister dst, Register src, uint8_t imm8,
3091cb0ef41Sopenharmony_ci                      uint32_t* load_pc_offset) {
3101cb0ef41Sopenharmony_ci    PinsrdPreSse41(dst, Operand(src), imm8, load_pc_offset);
3111cb0ef41Sopenharmony_ci  }
3121cb0ef41Sopenharmony_ci  void PinsrdPreSse41(XMMRegister dst, Operand src, uint8_t imm8,
3131cb0ef41Sopenharmony_ci                      uint32_t* load_pc_offset);
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci  // Expression support
3161cb0ef41Sopenharmony_ci  // cvtsi2sd instruction only writes to the low 64-bit of dst register, which
3171cb0ef41Sopenharmony_ci  // hinders register renaming and makes dependence chains longer. So we use
3181cb0ef41Sopenharmony_ci  // xorps to clear the dst register before cvtsi2sd to solve this issue.
3191cb0ef41Sopenharmony_ci  void Cvtsi2ss(XMMRegister dst, Register src) { Cvtsi2ss(dst, Operand(src)); }
3201cb0ef41Sopenharmony_ci  void Cvtsi2ss(XMMRegister dst, Operand src);
3211cb0ef41Sopenharmony_ci  void Cvtsi2sd(XMMRegister dst, Register src) { Cvtsi2sd(dst, Operand(src)); }
3221cb0ef41Sopenharmony_ci  void Cvtsi2sd(XMMRegister dst, Operand src);
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci  void Cvtui2ss(XMMRegister dst, Register src, Register tmp) {
3251cb0ef41Sopenharmony_ci    Cvtui2ss(dst, Operand(src), tmp);
3261cb0ef41Sopenharmony_ci  }
3271cb0ef41Sopenharmony_ci  void Cvtui2ss(XMMRegister dst, Operand src, Register tmp);
3281cb0ef41Sopenharmony_ci  void Cvttss2ui(Register dst, XMMRegister src, XMMRegister tmp) {
3291cb0ef41Sopenharmony_ci    Cvttss2ui(dst, Operand(src), tmp);
3301cb0ef41Sopenharmony_ci  }
3311cb0ef41Sopenharmony_ci  void Cvttss2ui(Register dst, Operand src, XMMRegister tmp);
3321cb0ef41Sopenharmony_ci  void Cvtui2sd(XMMRegister dst, Register src, Register scratch) {
3331cb0ef41Sopenharmony_ci    Cvtui2sd(dst, Operand(src), scratch);
3341cb0ef41Sopenharmony_ci  }
3351cb0ef41Sopenharmony_ci  void Cvtui2sd(XMMRegister dst, Operand src, Register scratch);
3361cb0ef41Sopenharmony_ci  void Cvttsd2ui(Register dst, XMMRegister src, XMMRegister tmp) {
3371cb0ef41Sopenharmony_ci    Cvttsd2ui(dst, Operand(src), tmp);
3381cb0ef41Sopenharmony_ci  }
3391cb0ef41Sopenharmony_ci  void Cvttsd2ui(Register dst, Operand src, XMMRegister tmp);
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  void Push(Register src) { push(src); }
3421cb0ef41Sopenharmony_ci  void Push(Operand src) { push(src); }
3431cb0ef41Sopenharmony_ci  void Push(Immediate value);
3441cb0ef41Sopenharmony_ci  void Push(Handle<HeapObject> handle) { push(Immediate(handle)); }
3451cb0ef41Sopenharmony_ci  void Push(Smi smi) { Push(Immediate(smi)); }
3461cb0ef41Sopenharmony_ci  void Push(XMMRegister src, Register scratch) {
3471cb0ef41Sopenharmony_ci    movd(scratch, src);
3481cb0ef41Sopenharmony_ci    push(scratch);
3491cb0ef41Sopenharmony_ci  }
3501cb0ef41Sopenharmony_ci
3511cb0ef41Sopenharmony_ci  void Pop(Register dst) { pop(dst); }
3521cb0ef41Sopenharmony_ci  void Pop(Operand dst) { pop(dst); }
3531cb0ef41Sopenharmony_ci  void Pop(XMMRegister dst, Register scratch) {
3541cb0ef41Sopenharmony_ci    pop(scratch);
3551cb0ef41Sopenharmony_ci    movd(dst, scratch);
3561cb0ef41Sopenharmony_ci  }
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ci  void MaybeSaveRegisters(RegList registers);
3591cb0ef41Sopenharmony_ci  void MaybeRestoreRegisters(RegList registers);
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci  void CallEphemeronKeyBarrier(Register object, Register slot_address,
3621cb0ef41Sopenharmony_ci                               SaveFPRegsMode fp_mode);
3631cb0ef41Sopenharmony_ci
3641cb0ef41Sopenharmony_ci  void CallRecordWriteStubSaveRegisters(
3651cb0ef41Sopenharmony_ci      Register object, Register slot_address,
3661cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
3671cb0ef41Sopenharmony_ci      StubCallMode mode = StubCallMode::kCallBuiltinPointer);
3681cb0ef41Sopenharmony_ci  void CallRecordWriteStub(
3691cb0ef41Sopenharmony_ci      Register object, Register slot_address,
3701cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
3711cb0ef41Sopenharmony_ci      StubCallMode mode = StubCallMode::kCallBuiltinPointer);
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci  // Calculate how much stack space (in bytes) are required to store caller
3741cb0ef41Sopenharmony_ci  // registers excluding those specified in the arguments.
3751cb0ef41Sopenharmony_ci  int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
3761cb0ef41Sopenharmony_ci                                      Register exclusion1 = no_reg,
3771cb0ef41Sopenharmony_ci                                      Register exclusion2 = no_reg,
3781cb0ef41Sopenharmony_ci                                      Register exclusion3 = no_reg) const;
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci  // PushCallerSaved and PopCallerSaved do not arrange the registers in any
3811cb0ef41Sopenharmony_ci  // particular order so they are not useful for calls that can cause a GC.
3821cb0ef41Sopenharmony_ci  // The caller can exclude up to 3 registers that do not need to be saved and
3831cb0ef41Sopenharmony_ci  // restored.
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ci  // Push caller saved registers on the stack, and return the number of bytes
3861cb0ef41Sopenharmony_ci  // stack pointer is adjusted.
3871cb0ef41Sopenharmony_ci  int PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
3881cb0ef41Sopenharmony_ci                      Register exclusion2 = no_reg,
3891cb0ef41Sopenharmony_ci                      Register exclusion3 = no_reg);
3901cb0ef41Sopenharmony_ci  // Restore caller saved registers from the stack, and return the number of
3911cb0ef41Sopenharmony_ci  // bytes stack pointer is adjusted.
3921cb0ef41Sopenharmony_ci  int PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
3931cb0ef41Sopenharmony_ci                     Register exclusion2 = no_reg,
3941cb0ef41Sopenharmony_ci                     Register exclusion3 = no_reg);
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ci  // Compute the start of the generated instruction stream from the current PC.
3971cb0ef41Sopenharmony_ci  // This is an alternative to embedding the {CodeObject} handle as a reference.
3981cb0ef41Sopenharmony_ci  void ComputeCodeStartAddress(Register dst);
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ci  // Control-flow integrity:
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci  // Define a function entrypoint. This doesn't emit any code for this
4031cb0ef41Sopenharmony_ci  // architecture, as control-flow integrity is not supported for it.
4041cb0ef41Sopenharmony_ci  void CodeEntry() {}
4051cb0ef41Sopenharmony_ci  // Define an exception handler.
4061cb0ef41Sopenharmony_ci  void ExceptionHandler() {}
4071cb0ef41Sopenharmony_ci  // Define an exception handler and bind a label.
4081cb0ef41Sopenharmony_ci  void BindExceptionHandler(Label* label) { bind(label); }
4091cb0ef41Sopenharmony_ci
4101cb0ef41Sopenharmony_ci protected:
4111cb0ef41Sopenharmony_ci  // Drops arguments assuming that the return address was already popped.
4121cb0ef41Sopenharmony_ci  void DropArguments(Register count, ArgumentsCountType type = kCountIsInteger,
4131cb0ef41Sopenharmony_ci                     ArgumentsCountMode mode = kCountExcludesReceiver);
4141cb0ef41Sopenharmony_ci};
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci// MacroAssembler implements a collection of frequently used macros.
4171cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
4181cb0ef41Sopenharmony_ci public:
4191cb0ef41Sopenharmony_ci  using TurboAssembler::TurboAssembler;
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_ci  void PushRoot(RootIndex index);
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci  // Compare the object in a register to a value and jump if they are equal.
4241cb0ef41Sopenharmony_ci  void JumpIfRoot(Register with, RootIndex index, Label* if_equal,
4251cb0ef41Sopenharmony_ci                  Label::Distance if_equal_distance = Label::kFar) {
4261cb0ef41Sopenharmony_ci    CompareRoot(with, index);
4271cb0ef41Sopenharmony_ci    j(equal, if_equal, if_equal_distance);
4281cb0ef41Sopenharmony_ci  }
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci  // Compare the object in a register to a value and jump if they are not equal.
4311cb0ef41Sopenharmony_ci  void JumpIfNotRoot(Register with, RootIndex index, Label* if_not_equal,
4321cb0ef41Sopenharmony_ci                     Label::Distance if_not_equal_distance = Label::kFar) {
4331cb0ef41Sopenharmony_ci    CompareRoot(with, index);
4341cb0ef41Sopenharmony_ci    j(not_equal, if_not_equal, if_not_equal_distance);
4351cb0ef41Sopenharmony_ci  }
4361cb0ef41Sopenharmony_ci
4371cb0ef41Sopenharmony_ci  // Checks if value is in range [lower_limit, higher_limit] using a single
4381cb0ef41Sopenharmony_ci  // comparison. Flags CF=1 or ZF=1 indicate the value is in the range
4391cb0ef41Sopenharmony_ci  // (condition below_equal). It is valid, that |value| == |scratch| as far as
4401cb0ef41Sopenharmony_ci  // this function is concerned.
4411cb0ef41Sopenharmony_ci  void CompareRange(Register value, unsigned lower_limit, unsigned higher_limit,
4421cb0ef41Sopenharmony_ci                    Register scratch);
4431cb0ef41Sopenharmony_ci  void JumpIfIsInRange(Register value, unsigned lower_limit,
4441cb0ef41Sopenharmony_ci                       unsigned higher_limit, Register scratch,
4451cb0ef41Sopenharmony_ci                       Label* on_in_range,
4461cb0ef41Sopenharmony_ci                       Label::Distance near_jump = Label::kFar);
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
4491cb0ef41Sopenharmony_ci  // GC Support
4501cb0ef41Sopenharmony_ci  // Notify the garbage collector that we wrote a pointer into an object.
4511cb0ef41Sopenharmony_ci  // |object| is the object being stored into, |value| is the object being
4521cb0ef41Sopenharmony_ci  // stored.  value and scratch registers are clobbered by the operation.
4531cb0ef41Sopenharmony_ci  // The offset is the offset from the start of the object, not the offset from
4541cb0ef41Sopenharmony_ci  // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
4551cb0ef41Sopenharmony_ci  void RecordWriteField(
4561cb0ef41Sopenharmony_ci      Register object, int offset, Register value, Register scratch,
4571cb0ef41Sopenharmony_ci      SaveFPRegsMode save_fp,
4581cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action = RememberedSetAction::kEmit,
4591cb0ef41Sopenharmony_ci      SmiCheck smi_check = SmiCheck::kInline);
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci  // For page containing |object| mark region covering |address|
4621cb0ef41Sopenharmony_ci  // dirty. |object| is the object being stored into, |value| is the
4631cb0ef41Sopenharmony_ci  // object being stored. The address and value registers are clobbered by the
4641cb0ef41Sopenharmony_ci  // operation. RecordWrite filters out smis so it does not update the
4651cb0ef41Sopenharmony_ci  // write barrier if the value is a smi.
4661cb0ef41Sopenharmony_ci  void RecordWrite(
4671cb0ef41Sopenharmony_ci      Register object, Register address, Register value, SaveFPRegsMode save_fp,
4681cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action = RememberedSetAction::kEmit,
4691cb0ef41Sopenharmony_ci      SmiCheck smi_check = SmiCheck::kInline);
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ci  // Enter specific kind of exit frame. Expects the number of
4721cb0ef41Sopenharmony_ci  // arguments in register eax and sets up the number of arguments in
4731cb0ef41Sopenharmony_ci  // register edi and the pointer to the first argument in register
4741cb0ef41Sopenharmony_ci  // esi.
4751cb0ef41Sopenharmony_ci  void EnterExitFrame(int argc, bool save_doubles, StackFrame::Type frame_type);
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ci  void EnterApiExitFrame(int argc, Register scratch);
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_ci  // Leave the current exit frame. Expects the return value in
4801cb0ef41Sopenharmony_ci  // register eax:edx (untouched) and the pointer to the first
4811cb0ef41Sopenharmony_ci  // argument in register esi (if pop_arguments == true).
4821cb0ef41Sopenharmony_ci  void LeaveExitFrame(bool save_doubles, bool pop_arguments = true);
4831cb0ef41Sopenharmony_ci
4841cb0ef41Sopenharmony_ci  // Leave the current exit frame. Expects the return value in
4851cb0ef41Sopenharmony_ci  // register eax (untouched).
4861cb0ef41Sopenharmony_ci  void LeaveApiExitFrame();
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_ci  // Load the global proxy from the current context.
4891cb0ef41Sopenharmony_ci  void LoadGlobalProxy(Register dst);
4901cb0ef41Sopenharmony_ci
4911cb0ef41Sopenharmony_ci  // Load a value from the native context with a given index.
4921cb0ef41Sopenharmony_ci  void LoadNativeContextSlot(Register dst, int index);
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
4951cb0ef41Sopenharmony_ci  // JavaScript invokes
4961cb0ef41Sopenharmony_ci
4971cb0ef41Sopenharmony_ci  // Invoke the JavaScript function code by either calling or jumping.
4981cb0ef41Sopenharmony_ci
4991cb0ef41Sopenharmony_ci  void InvokeFunctionCode(Register function, Register new_target,
5001cb0ef41Sopenharmony_ci                          Register expected_parameter_count,
5011cb0ef41Sopenharmony_ci                          Register actual_parameter_count, InvokeType type);
5021cb0ef41Sopenharmony_ci
5031cb0ef41Sopenharmony_ci  // On function call, call into the debugger.
5041cb0ef41Sopenharmony_ci  // This may clobber ecx.
5051cb0ef41Sopenharmony_ci  void CallDebugOnFunctionCall(Register fun, Register new_target,
5061cb0ef41Sopenharmony_ci                               Register expected_parameter_count,
5071cb0ef41Sopenharmony_ci                               Register actual_parameter_count);
5081cb0ef41Sopenharmony_ci
5091cb0ef41Sopenharmony_ci  // Invoke the JavaScript function in the given register. Changes the
5101cb0ef41Sopenharmony_ci  // current context to the context in the function before invoking.
5111cb0ef41Sopenharmony_ci  void InvokeFunction(Register function, Register new_target,
5121cb0ef41Sopenharmony_ci                      Register actual_parameter_count, InvokeType type);
5131cb0ef41Sopenharmony_ci
5141cb0ef41Sopenharmony_ci  // Compare object type for heap object.
5151cb0ef41Sopenharmony_ci  // Incoming register is heap_object and outgoing register is map.
5161cb0ef41Sopenharmony_ci  void CmpObjectType(Register heap_object, InstanceType type, Register map);
5171cb0ef41Sopenharmony_ci
5181cb0ef41Sopenharmony_ci  // Compare instance type for map.
5191cb0ef41Sopenharmony_ci  void CmpInstanceType(Register map, InstanceType type);
5201cb0ef41Sopenharmony_ci
5211cb0ef41Sopenharmony_ci  // Compare instance type ranges for a map (lower_limit and higher_limit
5221cb0ef41Sopenharmony_ci  // inclusive).
5231cb0ef41Sopenharmony_ci  //
5241cb0ef41Sopenharmony_ci  // Always use unsigned comparisons: below_equal for a positive
5251cb0ef41Sopenharmony_ci  // result.
5261cb0ef41Sopenharmony_ci  void CmpInstanceTypeRange(Register map, Register instance_type_out,
5271cb0ef41Sopenharmony_ci                            Register scratch, InstanceType lower_limit,
5281cb0ef41Sopenharmony_ci                            InstanceType higher_limit);
5291cb0ef41Sopenharmony_ci
5301cb0ef41Sopenharmony_ci  // Smi tagging support.
5311cb0ef41Sopenharmony_ci  void SmiTag(Register reg) {
5321cb0ef41Sopenharmony_ci    STATIC_ASSERT(kSmiTag == 0);
5331cb0ef41Sopenharmony_ci    STATIC_ASSERT(kSmiTagSize == 1);
5341cb0ef41Sopenharmony_ci    add(reg, reg);
5351cb0ef41Sopenharmony_ci  }
5361cb0ef41Sopenharmony_ci
5371cb0ef41Sopenharmony_ci  // Jump if register contain a non-smi.
5381cb0ef41Sopenharmony_ci  inline void JumpIfNotSmi(Register value, Label* not_smi_label,
5391cb0ef41Sopenharmony_ci                           Label::Distance distance = Label::kFar) {
5401cb0ef41Sopenharmony_ci    test(value, Immediate(kSmiTagMask));
5411cb0ef41Sopenharmony_ci    j(not_zero, not_smi_label, distance);
5421cb0ef41Sopenharmony_ci  }
5431cb0ef41Sopenharmony_ci  // Jump if the operand is not a smi.
5441cb0ef41Sopenharmony_ci  inline void JumpIfNotSmi(Operand value, Label* smi_label,
5451cb0ef41Sopenharmony_ci                           Label::Distance distance = Label::kFar) {
5461cb0ef41Sopenharmony_ci    test(value, Immediate(kSmiTagMask));
5471cb0ef41Sopenharmony_ci    j(not_zero, smi_label, distance);
5481cb0ef41Sopenharmony_ci  }
5491cb0ef41Sopenharmony_ci
5501cb0ef41Sopenharmony_ci  template <typename Field>
5511cb0ef41Sopenharmony_ci  void DecodeField(Register reg) {
5521cb0ef41Sopenharmony_ci    static const int shift = Field::kShift;
5531cb0ef41Sopenharmony_ci    static const int mask = Field::kMask >> Field::kShift;
5541cb0ef41Sopenharmony_ci    if (shift != 0) {
5551cb0ef41Sopenharmony_ci      sar(reg, shift);
5561cb0ef41Sopenharmony_ci    }
5571cb0ef41Sopenharmony_ci    and_(reg, Immediate(mask));
5581cb0ef41Sopenharmony_ci  }
5591cb0ef41Sopenharmony_ci
5601cb0ef41Sopenharmony_ci  // Abort execution if argument is not a smi, enabled via --debug-code.
5611cb0ef41Sopenharmony_ci  void AssertSmi(Register object);
5621cb0ef41Sopenharmony_ci
5631cb0ef41Sopenharmony_ci  // Abort execution if argument is a smi, enabled via --debug-code.
5641cb0ef41Sopenharmony_ci  void AssertNotSmi(Register object);
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_ci  // Abort execution if argument is not a JSFunction, enabled via --debug-code.
5671cb0ef41Sopenharmony_ci  void AssertFunction(Register object, Register scratch);
5681cb0ef41Sopenharmony_ci
5691cb0ef41Sopenharmony_ci  // Abort execution if argument is not a callable JSFunction, enabled via
5701cb0ef41Sopenharmony_ci  // --debug-code.
5711cb0ef41Sopenharmony_ci  void AssertCallableFunction(Register object, Register scratch);
5721cb0ef41Sopenharmony_ci
5731cb0ef41Sopenharmony_ci  // Abort execution if argument is not a Constructor, enabled via --debug-code.
5741cb0ef41Sopenharmony_ci  void AssertConstructor(Register object);
5751cb0ef41Sopenharmony_ci
5761cb0ef41Sopenharmony_ci  // Abort execution if argument is not a JSBoundFunction,
5771cb0ef41Sopenharmony_ci  // enabled via --debug-code.
5781cb0ef41Sopenharmony_ci  void AssertBoundFunction(Register object);
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ci  // Abort execution if argument is not a JSGeneratorObject (or subclass),
5811cb0ef41Sopenharmony_ci  // enabled via --debug-code.
5821cb0ef41Sopenharmony_ci  void AssertGeneratorObject(Register object);
5831cb0ef41Sopenharmony_ci
5841cb0ef41Sopenharmony_ci  // Abort execution if argument is not undefined or an AllocationSite, enabled
5851cb0ef41Sopenharmony_ci  // via --debug-code.
5861cb0ef41Sopenharmony_ci  void AssertUndefinedOrAllocationSite(Register object, Register scratch);
5871cb0ef41Sopenharmony_ci
5881cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
5891cb0ef41Sopenharmony_ci  // Exception handling
5901cb0ef41Sopenharmony_ci
5911cb0ef41Sopenharmony_ci  // Push a new stack handler and link it into stack handler chain.
5921cb0ef41Sopenharmony_ci  void PushStackHandler(Register scratch);
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ci  // Unlink the stack handler on top of the stack from the stack handler chain.
5951cb0ef41Sopenharmony_ci  void PopStackHandler(Register scratch);
5961cb0ef41Sopenharmony_ci
5971cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
5981cb0ef41Sopenharmony_ci  // Runtime calls
5991cb0ef41Sopenharmony_ci
6001cb0ef41Sopenharmony_ci  // Call a runtime routine.
6011cb0ef41Sopenharmony_ci  void CallRuntime(const Runtime::Function* f, int num_arguments,
6021cb0ef41Sopenharmony_ci                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore);
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_ci  // Convenience function: Same as above, but takes the fid instead.
6051cb0ef41Sopenharmony_ci  void CallRuntime(Runtime::FunctionId fid,
6061cb0ef41Sopenharmony_ci                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) {
6071cb0ef41Sopenharmony_ci    const Runtime::Function* function = Runtime::FunctionForId(fid);
6081cb0ef41Sopenharmony_ci    CallRuntime(function, function->nargs, save_doubles);
6091cb0ef41Sopenharmony_ci  }
6101cb0ef41Sopenharmony_ci
6111cb0ef41Sopenharmony_ci  // Convenience function: Same as above, but takes the fid instead.
6121cb0ef41Sopenharmony_ci  void CallRuntime(Runtime::FunctionId fid, int num_arguments,
6131cb0ef41Sopenharmony_ci                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) {
6141cb0ef41Sopenharmony_ci    CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles);
6151cb0ef41Sopenharmony_ci  }
6161cb0ef41Sopenharmony_ci
6171cb0ef41Sopenharmony_ci  // Convenience function: tail call a runtime routine (jump).
6181cb0ef41Sopenharmony_ci  void TailCallRuntime(Runtime::FunctionId fid);
6191cb0ef41Sopenharmony_ci
6201cb0ef41Sopenharmony_ci  // Jump to a runtime routine.
6211cb0ef41Sopenharmony_ci  void JumpToExternalReference(const ExternalReference& ext,
6221cb0ef41Sopenharmony_ci                               bool builtin_exit_frame = false);
6231cb0ef41Sopenharmony_ci
6241cb0ef41Sopenharmony_ci  // Generates a trampoline to jump to the off-heap instruction stream.
6251cb0ef41Sopenharmony_ci  void JumpToOffHeapInstructionStream(Address entry);
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
6281cb0ef41Sopenharmony_ci  // Utilities
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci  // Emit code to discard a non-negative number of pointer-sized elements
6311cb0ef41Sopenharmony_ci  // from the stack, clobbering only the esp register.
6321cb0ef41Sopenharmony_ci  void Drop(int element_count);
6331cb0ef41Sopenharmony_ci
6341cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
6351cb0ef41Sopenharmony_ci  // In-place weak references.
6361cb0ef41Sopenharmony_ci  void LoadWeakValue(Register in_out, Label* target_if_cleared);
6371cb0ef41Sopenharmony_ci
6381cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
6391cb0ef41Sopenharmony_ci  // StatsCounter support
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ci  void IncrementCounter(StatsCounter* counter, int value, Register scratch) {
6421cb0ef41Sopenharmony_ci    if (!FLAG_native_code_counters) return;
6431cb0ef41Sopenharmony_ci    EmitIncrementCounter(counter, value, scratch);
6441cb0ef41Sopenharmony_ci  }
6451cb0ef41Sopenharmony_ci  void EmitIncrementCounter(StatsCounter* counter, int value, Register scratch);
6461cb0ef41Sopenharmony_ci  void DecrementCounter(StatsCounter* counter, int value, Register scratch) {
6471cb0ef41Sopenharmony_ci    if (!FLAG_native_code_counters) return;
6481cb0ef41Sopenharmony_ci    EmitDecrementCounter(counter, value, scratch);
6491cb0ef41Sopenharmony_ci  }
6501cb0ef41Sopenharmony_ci  void EmitDecrementCounter(StatsCounter* counter, int value, Register scratch);
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
6531cb0ef41Sopenharmony_ci  // Stack limit utilities
6541cb0ef41Sopenharmony_ci  void CompareStackLimit(Register with, StackLimitKind kind);
6551cb0ef41Sopenharmony_ci  void StackOverflowCheck(Register num_args, Register scratch,
6561cb0ef41Sopenharmony_ci                          Label* stack_overflow, bool include_receiver = false);
6571cb0ef41Sopenharmony_ci
6581cb0ef41Sopenharmony_ci private:
6591cb0ef41Sopenharmony_ci  // Helper functions for generating invokes.
6601cb0ef41Sopenharmony_ci  void InvokePrologue(Register expected_parameter_count,
6611cb0ef41Sopenharmony_ci                      Register actual_parameter_count, Label* done,
6621cb0ef41Sopenharmony_ci                      InvokeType type);
6631cb0ef41Sopenharmony_ci
6641cb0ef41Sopenharmony_ci  void EnterExitFramePrologue(StackFrame::Type frame_type, Register scratch);
6651cb0ef41Sopenharmony_ci  void EnterExitFrameEpilogue(int argc, bool save_doubles);
6661cb0ef41Sopenharmony_ci
6671cb0ef41Sopenharmony_ci  void LeaveExitFrameEpilogue();
6681cb0ef41Sopenharmony_ci
6691cb0ef41Sopenharmony_ci  DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
6701cb0ef41Sopenharmony_ci};
6711cb0ef41Sopenharmony_ci
6721cb0ef41Sopenharmony_ci// -----------------------------------------------------------------------------
6731cb0ef41Sopenharmony_ci// Static helper functions.
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_ci// Generate an Operand for loading a field from an object.
6761cb0ef41Sopenharmony_ciinline Operand FieldOperand(Register object, int offset) {
6771cb0ef41Sopenharmony_ci  return Operand(object, offset - kHeapObjectTag);
6781cb0ef41Sopenharmony_ci}
6791cb0ef41Sopenharmony_ci
6801cb0ef41Sopenharmony_ci// Generate an Operand for loading an indexed field from an object.
6811cb0ef41Sopenharmony_ciinline Operand FieldOperand(Register object, Register index, ScaleFactor scale,
6821cb0ef41Sopenharmony_ci                            int offset) {
6831cb0ef41Sopenharmony_ci  return Operand(object, index, scale, offset - kHeapObjectTag);
6841cb0ef41Sopenharmony_ci}
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ci#define ACCESS_MASM(masm) masm->
6871cb0ef41Sopenharmony_ci
6881cb0ef41Sopenharmony_ci}  // namespace internal
6891cb0ef41Sopenharmony_ci}  // namespace v8
6901cb0ef41Sopenharmony_ci
6911cb0ef41Sopenharmony_ci#endif  // V8_CODEGEN_IA32_MACRO_ASSEMBLER_IA32_H_
692