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_X64_MACRO_ASSEMBLER_X64_H_
101cb0ef41Sopenharmony_ci#define V8_CODEGEN_X64_MACRO_ASSEMBLER_X64_H_
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include "src/base/flags.h"
131cb0ef41Sopenharmony_ci#include "src/codegen/bailout-reason.h"
141cb0ef41Sopenharmony_ci#include "src/codegen/shared-ia32-x64/macro-assembler-shared-ia32-x64.h"
151cb0ef41Sopenharmony_ci#include "src/codegen/x64/assembler-x64.h"
161cb0ef41Sopenharmony_ci#include "src/common/globals.h"
171cb0ef41Sopenharmony_ci#include "src/execution/isolate-data.h"
181cb0ef41Sopenharmony_ci#include "src/objects/contexts.h"
191cb0ef41Sopenharmony_ci#include "src/objects/tagged-index.h"
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_cinamespace v8 {
221cb0ef41Sopenharmony_cinamespace internal {
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci// Convenience for platform-independent signatures.
251cb0ef41Sopenharmony_ciusing MemOperand = Operand;
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciclass StringConstantBase;
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_cistruct SmiIndex {
301cb0ef41Sopenharmony_ci  SmiIndex(Register index_register, ScaleFactor scale)
311cb0ef41Sopenharmony_ci      : reg(index_register), scale(scale) {}
321cb0ef41Sopenharmony_ci  Register reg;
331cb0ef41Sopenharmony_ci  ScaleFactor scale;
341cb0ef41Sopenharmony_ci};
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci// TODO(victorgomes): Move definition to macro-assembler.h, once all other
371cb0ef41Sopenharmony_ci// platforms are updated.
381cb0ef41Sopenharmony_cienum class StackLimitKind { kInterruptStackLimit, kRealStackLimit };
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci// Convenient class to access arguments below the stack pointer.
411cb0ef41Sopenharmony_ciclass StackArgumentsAccessor {
421cb0ef41Sopenharmony_ci public:
431cb0ef41Sopenharmony_ci  // argc = the number of arguments not including the receiver.
441cb0ef41Sopenharmony_ci  explicit StackArgumentsAccessor(Register argc) : argc_(argc) {
451cb0ef41Sopenharmony_ci    DCHECK_NE(argc_, no_reg);
461cb0ef41Sopenharmony_ci  }
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  // Argument 0 is the receiver (despite argc not including the receiver).
491cb0ef41Sopenharmony_ci  Operand operator[](int index) const { return GetArgumentOperand(index); }
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  Operand GetArgumentOperand(int index) const;
521cb0ef41Sopenharmony_ci  Operand GetReceiverOperand() const { return GetArgumentOperand(0); }
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci private:
551cb0ef41Sopenharmony_ci  const Register argc_;
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  DISALLOW_IMPLICIT_CONSTRUCTORS(StackArgumentsAccessor);
581cb0ef41Sopenharmony_ci};
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE TurboAssembler
611cb0ef41Sopenharmony_ci    : public SharedTurboAssemblerBase<TurboAssembler> {
621cb0ef41Sopenharmony_ci public:
631cb0ef41Sopenharmony_ci  using SharedTurboAssemblerBase<TurboAssembler>::SharedTurboAssemblerBase;
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  void PushReturnAddressFrom(Register src) { pushq(src); }
661cb0ef41Sopenharmony_ci  void PopReturnAddressTo(Register dst) { popq(dst); }
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  void Ret();
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  // Call incsspq with {number_of_words} only if the cpu supports it.
711cb0ef41Sopenharmony_ci  // NOTE: This shouldn't be embedded in optimized code, since the check
721cb0ef41Sopenharmony_ci  // for CPU support would be redundant (we could check at compiler time).
731cb0ef41Sopenharmony_ci  void IncsspqIfSupported(Register number_of_words, Register scratch);
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  // Return and drop arguments from stack, where the number of arguments
761cb0ef41Sopenharmony_ci  // may be bigger than 2^16 - 1.  Requires a scratch register.
771cb0ef41Sopenharmony_ci  void Ret(int bytes_dropped, Register scratch);
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  // Operations on roots in the root-array.
801cb0ef41Sopenharmony_ci  Operand RootAsOperand(RootIndex index);
811cb0ef41Sopenharmony_ci  void LoadRoot(Register destination, RootIndex index) final;
821cb0ef41Sopenharmony_ci  void LoadRoot(Operand destination, RootIndex index) {
831cb0ef41Sopenharmony_ci    LoadRoot(kScratchRegister, index);
841cb0ef41Sopenharmony_ci    movq(destination, kScratchRegister);
851cb0ef41Sopenharmony_ci  }
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  void Push(Register src);
881cb0ef41Sopenharmony_ci  void Push(Operand src);
891cb0ef41Sopenharmony_ci  void Push(Immediate value);
901cb0ef41Sopenharmony_ci  void Push(Smi smi);
911cb0ef41Sopenharmony_ci  void Push(TaggedIndex index) {
921cb0ef41Sopenharmony_ci    Push(Immediate(static_cast<uint32_t>(index.ptr())));
931cb0ef41Sopenharmony_ci  }
941cb0ef41Sopenharmony_ci  void Push(Handle<HeapObject> source);
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  enum class PushArrayOrder { kNormal, kReverse };
971cb0ef41Sopenharmony_ci  // `array` points to the first element (the lowest address).
981cb0ef41Sopenharmony_ci  // `array` and `size` are not modified.
991cb0ef41Sopenharmony_ci  void PushArray(Register array, Register size, Register scratch,
1001cb0ef41Sopenharmony_ci                 PushArrayOrder order = PushArrayOrder::kNormal);
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  // Before calling a C-function from generated code, align arguments on stack.
1031cb0ef41Sopenharmony_ci  // After aligning the frame, arguments must be stored in rsp[0], rsp[8],
1041cb0ef41Sopenharmony_ci  // etc., not pushed. The argument count assumes all arguments are word sized.
1051cb0ef41Sopenharmony_ci  // The number of slots reserved for arguments depends on platform. On Windows
1061cb0ef41Sopenharmony_ci  // stack slots are reserved for the arguments passed in registers. On other
1071cb0ef41Sopenharmony_ci  // platforms stack slots are only reserved for the arguments actually passed
1081cb0ef41Sopenharmony_ci  // on the stack.
1091cb0ef41Sopenharmony_ci  void PrepareCallCFunction(int num_arguments);
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  // Calls a C function and cleans up the space for arguments allocated
1121cb0ef41Sopenharmony_ci  // by PrepareCallCFunction. The called function is not allowed to trigger a
1131cb0ef41Sopenharmony_ci  // garbage collection, since that might move the code and invalidate the
1141cb0ef41Sopenharmony_ci  // return address (unless this is somehow accounted for by the called
1151cb0ef41Sopenharmony_ci  // function).
1161cb0ef41Sopenharmony_ci  void CallCFunction(ExternalReference function, int num_arguments);
1171cb0ef41Sopenharmony_ci  void CallCFunction(Register function, int num_arguments);
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  // Calculate the number of stack slots to reserve for arguments when calling a
1201cb0ef41Sopenharmony_ci  // C function.
1211cb0ef41Sopenharmony_ci  int ArgumentStackSlotsForCFunctionCall(int num_arguments);
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  void CheckPageFlag(Register object, Register scratch, int mask, Condition cc,
1241cb0ef41Sopenharmony_ci                     Label* condition_met,
1251cb0ef41Sopenharmony_ci                     Label::Distance condition_met_distance = Label::kFar);
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  // Define movq here instead of using AVX_OP. movq is defined using templates
1281cb0ef41Sopenharmony_ci  // and there is a function template `void movq(P1)`, while technically
1291cb0ef41Sopenharmony_ci  // impossible, will be selected when deducing the arguments for AvxHelper.
1301cb0ef41Sopenharmony_ci  void Movq(XMMRegister dst, Register src);
1311cb0ef41Sopenharmony_ci  void Movq(Register dst, XMMRegister src);
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  void Cvtss2sd(XMMRegister dst, XMMRegister src);
1341cb0ef41Sopenharmony_ci  void Cvtss2sd(XMMRegister dst, Operand src);
1351cb0ef41Sopenharmony_ci  void Cvtsd2ss(XMMRegister dst, XMMRegister src);
1361cb0ef41Sopenharmony_ci  void Cvtsd2ss(XMMRegister dst, Operand src);
1371cb0ef41Sopenharmony_ci  void Cvttsd2si(Register dst, XMMRegister src);
1381cb0ef41Sopenharmony_ci  void Cvttsd2si(Register dst, Operand src);
1391cb0ef41Sopenharmony_ci  void Cvttsd2siq(Register dst, XMMRegister src);
1401cb0ef41Sopenharmony_ci  void Cvttsd2siq(Register dst, Operand src);
1411cb0ef41Sopenharmony_ci  void Cvttss2si(Register dst, XMMRegister src);
1421cb0ef41Sopenharmony_ci  void Cvttss2si(Register dst, Operand src);
1431cb0ef41Sopenharmony_ci  void Cvttss2siq(Register dst, XMMRegister src);
1441cb0ef41Sopenharmony_ci  void Cvttss2siq(Register dst, Operand src);
1451cb0ef41Sopenharmony_ci  void Cvtlui2ss(XMMRegister dst, Register src);
1461cb0ef41Sopenharmony_ci  void Cvtlui2ss(XMMRegister dst, Operand src);
1471cb0ef41Sopenharmony_ci  void Cvtlui2sd(XMMRegister dst, Register src);
1481cb0ef41Sopenharmony_ci  void Cvtlui2sd(XMMRegister dst, Operand src);
1491cb0ef41Sopenharmony_ci  void Cvtqui2ss(XMMRegister dst, Register src);
1501cb0ef41Sopenharmony_ci  void Cvtqui2ss(XMMRegister dst, Operand src);
1511cb0ef41Sopenharmony_ci  void Cvtqui2sd(XMMRegister dst, Register src);
1521cb0ef41Sopenharmony_ci  void Cvtqui2sd(XMMRegister dst, Operand src);
1531cb0ef41Sopenharmony_ci  void Cvttsd2uiq(Register dst, Operand src, Label* fail = nullptr);
1541cb0ef41Sopenharmony_ci  void Cvttsd2uiq(Register dst, XMMRegister src, Label* fail = nullptr);
1551cb0ef41Sopenharmony_ci  void Cvttss2uiq(Register dst, Operand src, Label* fail = nullptr);
1561cb0ef41Sopenharmony_ci  void Cvttss2uiq(Register dst, XMMRegister src, Label* fail = nullptr);
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci  // cvtsi2sd and cvtsi2ss instructions only write to the low 64/32-bit of dst
1591cb0ef41Sopenharmony_ci  // register, which hinders register renaming and makes dependence chains
1601cb0ef41Sopenharmony_ci  // longer. So we use xorpd to clear the dst register before cvtsi2sd for
1611cb0ef41Sopenharmony_ci  // non-AVX and a scratch XMM register as first src for AVX to solve this
1621cb0ef41Sopenharmony_ci  // issue.
1631cb0ef41Sopenharmony_ci  void Cvtqsi2ss(XMMRegister dst, Register src);
1641cb0ef41Sopenharmony_ci  void Cvtqsi2ss(XMMRegister dst, Operand src);
1651cb0ef41Sopenharmony_ci  void Cvtqsi2sd(XMMRegister dst, Register src);
1661cb0ef41Sopenharmony_ci  void Cvtqsi2sd(XMMRegister dst, Operand src);
1671cb0ef41Sopenharmony_ci  void Cvtlsi2ss(XMMRegister dst, Register src);
1681cb0ef41Sopenharmony_ci  void Cvtlsi2ss(XMMRegister dst, Operand src);
1691cb0ef41Sopenharmony_ci  void Cvtlsi2sd(XMMRegister dst, Register src);
1701cb0ef41Sopenharmony_ci  void Cvtlsi2sd(XMMRegister dst, Operand src);
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  void Cmpeqss(XMMRegister dst, XMMRegister src);
1731cb0ef41Sopenharmony_ci  void Cmpeqsd(XMMRegister dst, XMMRegister src);
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  void PextrdPreSse41(Register dst, XMMRegister src, uint8_t imm8);
1761cb0ef41Sopenharmony_ci  void Pextrq(Register dst, XMMRegister src, int8_t imm8);
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci  void PinsrdPreSse41(XMMRegister dst, Register src2, uint8_t imm8,
1791cb0ef41Sopenharmony_ci                      uint32_t* load_pc_offset = nullptr);
1801cb0ef41Sopenharmony_ci  void PinsrdPreSse41(XMMRegister dst, Operand src2, uint8_t imm8,
1811cb0ef41Sopenharmony_ci                      uint32_t* load_pc_offset = nullptr);
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci  void Pinsrq(XMMRegister dst, XMMRegister src1, Register src2, uint8_t imm8,
1841cb0ef41Sopenharmony_ci              uint32_t* load_pc_offset = nullptr);
1851cb0ef41Sopenharmony_ci  void Pinsrq(XMMRegister dst, XMMRegister src1, Operand src2, uint8_t imm8,
1861cb0ef41Sopenharmony_ci              uint32_t* load_pc_offset = nullptr);
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci  void Lzcntq(Register dst, Register src);
1891cb0ef41Sopenharmony_ci  void Lzcntq(Register dst, Operand src);
1901cb0ef41Sopenharmony_ci  void Lzcntl(Register dst, Register src);
1911cb0ef41Sopenharmony_ci  void Lzcntl(Register dst, Operand src);
1921cb0ef41Sopenharmony_ci  void Tzcntq(Register dst, Register src);
1931cb0ef41Sopenharmony_ci  void Tzcntq(Register dst, Operand src);
1941cb0ef41Sopenharmony_ci  void Tzcntl(Register dst, Register src);
1951cb0ef41Sopenharmony_ci  void Tzcntl(Register dst, Operand src);
1961cb0ef41Sopenharmony_ci  void Popcntl(Register dst, Register src);
1971cb0ef41Sopenharmony_ci  void Popcntl(Register dst, Operand src);
1981cb0ef41Sopenharmony_ci  void Popcntq(Register dst, Register src);
1991cb0ef41Sopenharmony_ci  void Popcntq(Register dst, Operand src);
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci  void Cmp(Register dst, Smi src);
2021cb0ef41Sopenharmony_ci  void Cmp(Operand dst, Smi src);
2031cb0ef41Sopenharmony_ci  void Cmp(Register dst, int32_t src);
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
2061cb0ef41Sopenharmony_ci  // Conversions between tagged smi values and non-tagged integer values.
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  // Tag an word-size value. The result must be known to be a valid smi value.
2091cb0ef41Sopenharmony_ci  void SmiTag(Register reg);
2101cb0ef41Sopenharmony_ci  // Requires dst != src
2111cb0ef41Sopenharmony_ci  void SmiTag(Register dst, Register src);
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci  // Simple comparison of smis.  Both sides must be known smis to use these,
2141cb0ef41Sopenharmony_ci  // otherwise use Cmp.
2151cb0ef41Sopenharmony_ci  void SmiCompare(Register smi1, Register smi2);
2161cb0ef41Sopenharmony_ci  void SmiCompare(Register dst, Smi src);
2171cb0ef41Sopenharmony_ci  void SmiCompare(Register dst, Operand src);
2181cb0ef41Sopenharmony_ci  void SmiCompare(Operand dst, Register src);
2191cb0ef41Sopenharmony_ci  void SmiCompare(Operand dst, Smi src);
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci  // Functions performing a check on a known or potential smi. Returns
2221cb0ef41Sopenharmony_ci  // a condition that is satisfied if the check is successful.
2231cb0ef41Sopenharmony_ci  Condition CheckSmi(Register src);
2241cb0ef41Sopenharmony_ci  Condition CheckSmi(Operand src);
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci  // Abort execution if argument is a smi, enabled via --debug-code.
2271cb0ef41Sopenharmony_ci  void AssertNotSmi(Register object);
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  // Abort execution if argument is not a smi, enabled via --debug-code.
2301cb0ef41Sopenharmony_ci  void AssertSmi(Register object);
2311cb0ef41Sopenharmony_ci  void AssertSmi(Operand object);
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci  // Test-and-jump functions. Typically combines a check function
2341cb0ef41Sopenharmony_ci  // above with a conditional jump.
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci  // Jump to label if the value is a tagged smi.
2371cb0ef41Sopenharmony_ci  void JumpIfSmi(Register src, Label* on_smi,
2381cb0ef41Sopenharmony_ci                 Label::Distance near_jump = Label::kFar);
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci  // Jump to label if the value is not a tagged smi.
2411cb0ef41Sopenharmony_ci  void JumpIfNotSmi(Register src, Label* on_not_smi,
2421cb0ef41Sopenharmony_ci                    Label::Distance near_jump = Label::kFar);
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci  // Jump to label if the value is not a tagged smi.
2451cb0ef41Sopenharmony_ci  void JumpIfNotSmi(Operand src, Label* on_not_smi,
2461cb0ef41Sopenharmony_ci                    Label::Distance near_jump = Label::kFar);
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci  // Operations on tagged smi values.
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci  // Smis represent a subset of integers. The subset is always equivalent to
2511cb0ef41Sopenharmony_ci  // a two's complement interpretation of a fixed number of bits.
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci  // Add an integer constant to a tagged smi, giving a tagged smi as result.
2541cb0ef41Sopenharmony_ci  // No overflow testing on the result is done.
2551cb0ef41Sopenharmony_ci  void SmiAddConstant(Operand dst, Smi constant);
2561cb0ef41Sopenharmony_ci
2571cb0ef41Sopenharmony_ci  // Specialized operations
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci  // Converts, if necessary, a smi to a combination of number and
2601cb0ef41Sopenharmony_ci  // multiplier to be used as a scaled index.
2611cb0ef41Sopenharmony_ci  // The src register contains a *positive* smi value. The shift is the
2621cb0ef41Sopenharmony_ci  // power of two to multiply the index value by (e.g. to index by
2631cb0ef41Sopenharmony_ci  // smi-value * kSystemPointerSize, pass the smi and kSystemPointerSizeLog2).
2641cb0ef41Sopenharmony_ci  // The returned index register may be either src or dst, depending
2651cb0ef41Sopenharmony_ci  // on what is most efficient. If src and dst are different registers,
2661cb0ef41Sopenharmony_ci  // src is always unchanged.
2671cb0ef41Sopenharmony_ci  SmiIndex SmiToIndex(Register dst, Register src, int shift);
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci  void JumpIfEqual(Register a, int32_t b, Label* dest) {
2701cb0ef41Sopenharmony_ci    cmpl(a, Immediate(b));
2711cb0ef41Sopenharmony_ci    j(equal, dest);
2721cb0ef41Sopenharmony_ci  }
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci  void JumpIfLessThan(Register a, int32_t b, Label* dest) {
2751cb0ef41Sopenharmony_ci    cmpl(a, Immediate(b));
2761cb0ef41Sopenharmony_ci    j(less, dest);
2771cb0ef41Sopenharmony_ci  }
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci#ifdef V8_MAP_PACKING
2801cb0ef41Sopenharmony_ci  void UnpackMapWord(Register r);
2811cb0ef41Sopenharmony_ci#endif
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ci  void LoadMap(Register destination, Register object);
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci  void Move(Register dst, intptr_t x) {
2861cb0ef41Sopenharmony_ci    if (x == 0) {
2871cb0ef41Sopenharmony_ci      xorl(dst, dst);
2881cb0ef41Sopenharmony_ci      // The following shorter sequence for uint8 causes performance
2891cb0ef41Sopenharmony_ci      // regressions:
2901cb0ef41Sopenharmony_ci      // xorl(dst, dst); movb(dst,
2911cb0ef41Sopenharmony_ci      // Immediate(static_cast<uint32_t>(x)));
2921cb0ef41Sopenharmony_ci    } else if (is_uint32(x)) {
2931cb0ef41Sopenharmony_ci      movl(dst, Immediate(static_cast<uint32_t>(x)));
2941cb0ef41Sopenharmony_ci    } else if (is_int32(x)) {
2951cb0ef41Sopenharmony_ci      // "movq reg64, imm32" is sign extending.
2961cb0ef41Sopenharmony_ci      movq(dst, Immediate(static_cast<int32_t>(x)));
2971cb0ef41Sopenharmony_ci    } else {
2981cb0ef41Sopenharmony_ci      movq(dst, Immediate64(x));
2991cb0ef41Sopenharmony_ci    }
3001cb0ef41Sopenharmony_ci  }
3011cb0ef41Sopenharmony_ci  void Move(Operand dst, intptr_t x);
3021cb0ef41Sopenharmony_ci  void Move(Register dst, Smi source);
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_ci  void Move(Operand dst, Smi source) {
3051cb0ef41Sopenharmony_ci    Register constant = GetSmiConstant(source);
3061cb0ef41Sopenharmony_ci    movq(dst, constant);
3071cb0ef41Sopenharmony_ci  }
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci  void Move(Register dst, TaggedIndex source) { Move(dst, source.ptr()); }
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ci  void Move(Operand dst, TaggedIndex source) { Move(dst, source.ptr()); }
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci  void Move(Register dst, ExternalReference ext);
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci  void Move(XMMRegister dst, uint32_t src);
3161cb0ef41Sopenharmony_ci  void Move(XMMRegister dst, uint64_t src);
3171cb0ef41Sopenharmony_ci  void Move(XMMRegister dst, float src) { Move(dst, bit_cast<uint32_t>(src)); }
3181cb0ef41Sopenharmony_ci  void Move(XMMRegister dst, double src) { Move(dst, bit_cast<uint64_t>(src)); }
3191cb0ef41Sopenharmony_ci  void Move(XMMRegister dst, uint64_t high, uint64_t low);
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci  // Move if the registers are not identical.
3221cb0ef41Sopenharmony_ci  void Move(Register target, Register source);
3231cb0ef41Sopenharmony_ci  void Move(XMMRegister target, XMMRegister source);
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci  void Move(Register target, Operand source);
3261cb0ef41Sopenharmony_ci  void Move(Register target, Immediate source);
3271cb0ef41Sopenharmony_ci
3281cb0ef41Sopenharmony_ci  void Move(Register dst, Handle<HeapObject> source,
3291cb0ef41Sopenharmony_ci            RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT);
3301cb0ef41Sopenharmony_ci  void Move(Operand dst, Handle<HeapObject> source,
3311cb0ef41Sopenharmony_ci            RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT);
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci  // Loads a pointer into a register with a relocation mode.
3341cb0ef41Sopenharmony_ci  void Move(Register dst, Address ptr, RelocInfo::Mode rmode) {
3351cb0ef41Sopenharmony_ci    // This method must not be used with heap object references. The stored
3361cb0ef41Sopenharmony_ci    // address is not GC safe. Use the handle version instead.
3371cb0ef41Sopenharmony_ci    DCHECK(rmode == RelocInfo::NO_INFO || rmode > RelocInfo::LAST_GCED_ENUM);
3381cb0ef41Sopenharmony_ci    movq(dst, Immediate64(ptr, rmode));
3391cb0ef41Sopenharmony_ci  }
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  // Move src0 to dst0 and src1 to dst1, handling possible overlaps.
3421cb0ef41Sopenharmony_ci  void MovePair(Register dst0, Register src0, Register dst1, Register src1);
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci  void MoveStringConstant(
3451cb0ef41Sopenharmony_ci      Register result, const StringConstantBase* string,
3461cb0ef41Sopenharmony_ci      RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT);
3471cb0ef41Sopenharmony_ci
3481cb0ef41Sopenharmony_ci  // Convert smi to word-size sign-extended value.
3491cb0ef41Sopenharmony_ci  void SmiUntag(Register reg);
3501cb0ef41Sopenharmony_ci  // Requires dst != src
3511cb0ef41Sopenharmony_ci  void SmiUntag(Register dst, Register src);
3521cb0ef41Sopenharmony_ci  void SmiUntag(Register dst, Operand src);
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci  // Convert smi to 32-bit value.
3551cb0ef41Sopenharmony_ci  void SmiToInt32(Register reg);
3561cb0ef41Sopenharmony_ci
3571cb0ef41Sopenharmony_ci  // Loads the address of the external reference into the destination
3581cb0ef41Sopenharmony_ci  // register.
3591cb0ef41Sopenharmony_ci  void LoadAddress(Register destination, ExternalReference source);
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci  void LoadFromConstantsTable(Register destination, int constant_index) final;
3621cb0ef41Sopenharmony_ci  void LoadRootRegisterOffset(Register destination, intptr_t offset) final;
3631cb0ef41Sopenharmony_ci  void LoadRootRelative(Register destination, int32_t offset) final;
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ci  // Operand pointing to an external reference.
3661cb0ef41Sopenharmony_ci  // May emit code to set up the scratch register. The operand is
3671cb0ef41Sopenharmony_ci  // only guaranteed to be correct as long as the scratch register
3681cb0ef41Sopenharmony_ci  // isn't changed.
3691cb0ef41Sopenharmony_ci  // If the operand is used more than once, use a scratch register
3701cb0ef41Sopenharmony_ci  // that is guaranteed not to be clobbered.
3711cb0ef41Sopenharmony_ci  Operand ExternalReferenceAsOperand(ExternalReference reference,
3721cb0ef41Sopenharmony_ci                                     Register scratch = kScratchRegister);
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ci  void Call(Register reg) { call(reg); }
3751cb0ef41Sopenharmony_ci  void Call(Operand op);
3761cb0ef41Sopenharmony_ci  void Call(Handle<CodeT> code_object, RelocInfo::Mode rmode);
3771cb0ef41Sopenharmony_ci  void Call(Address destination, RelocInfo::Mode rmode);
3781cb0ef41Sopenharmony_ci  void Call(ExternalReference ext);
3791cb0ef41Sopenharmony_ci  void Call(Label* target) { call(target); }
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ci  Operand EntryFromBuiltinAsOperand(Builtin builtin_index);
3821cb0ef41Sopenharmony_ci  Operand EntryFromBuiltinIndexAsOperand(Register builtin_index);
3831cb0ef41Sopenharmony_ci  void CallBuiltinByIndex(Register builtin_index);
3841cb0ef41Sopenharmony_ci  void CallBuiltin(Builtin builtin);
3851cb0ef41Sopenharmony_ci  void TailCallBuiltin(Builtin builtin);
3861cb0ef41Sopenharmony_ci
3871cb0ef41Sopenharmony_ci  void LoadCodeObjectEntry(Register destination, Register code_object);
3881cb0ef41Sopenharmony_ci  void CallCodeObject(Register code_object);
3891cb0ef41Sopenharmony_ci  void JumpCodeObject(Register code_object,
3901cb0ef41Sopenharmony_ci                      JumpMode jump_mode = JumpMode::kJump);
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci  // Load code entry point from the CodeDataContainer object.
3931cb0ef41Sopenharmony_ci  void LoadCodeDataContainerEntry(Register destination,
3941cb0ef41Sopenharmony_ci                                  Register code_data_container_object);
3951cb0ef41Sopenharmony_ci  // Load code entry point from the CodeDataContainer object and compute
3961cb0ef41Sopenharmony_ci  // Code object pointer out of it. Must not be used for CodeDataContainers
3971cb0ef41Sopenharmony_ci  // corresponding to builtins, because their entry points values point to
3981cb0ef41Sopenharmony_ci  // the embedded instruction stream in .text section.
3991cb0ef41Sopenharmony_ci  void LoadCodeDataContainerCodeNonBuiltin(Register destination,
4001cb0ef41Sopenharmony_ci                                           Register code_data_container_object);
4011cb0ef41Sopenharmony_ci  void CallCodeDataContainerObject(Register code_data_container_object);
4021cb0ef41Sopenharmony_ci  void JumpCodeDataContainerObject(Register code_data_container_object,
4031cb0ef41Sopenharmony_ci                                   JumpMode jump_mode = JumpMode::kJump);
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci  // Helper functions that dispatch either to Call/JumpCodeObject or to
4061cb0ef41Sopenharmony_ci  // Call/JumpCodeDataContainerObject.
4071cb0ef41Sopenharmony_ci  // TODO(v8:11880): remove since CodeT targets are now default.
4081cb0ef41Sopenharmony_ci  void LoadCodeTEntry(Register destination, Register code);
4091cb0ef41Sopenharmony_ci  void CallCodeTObject(Register code);
4101cb0ef41Sopenharmony_ci  void JumpCodeTObject(Register code, JumpMode jump_mode = JumpMode::kJump);
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci  void Jump(Address destination, RelocInfo::Mode rmode);
4131cb0ef41Sopenharmony_ci  void Jump(const ExternalReference& reference);
4141cb0ef41Sopenharmony_ci  void Jump(Operand op);
4151cb0ef41Sopenharmony_ci  void Jump(Handle<CodeT> code_object, RelocInfo::Mode rmode,
4161cb0ef41Sopenharmony_ci            Condition cc = always);
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci  void BailoutIfDeoptimized(Register scratch);
4191cb0ef41Sopenharmony_ci  void CallForDeoptimization(Builtin target, int deopt_id, Label* exit,
4201cb0ef41Sopenharmony_ci                             DeoptimizeKind kind, Label* ret,
4211cb0ef41Sopenharmony_ci                             Label* jump_deoptimization_entry_label);
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci  void Trap();
4241cb0ef41Sopenharmony_ci  void DebugBreak();
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci  void CompareRoot(Register with, RootIndex index);
4271cb0ef41Sopenharmony_ci  void CompareRoot(Operand with, RootIndex index);
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci  // Generates function and stub prologue code.
4301cb0ef41Sopenharmony_ci  void StubPrologue(StackFrame::Type type);
4311cb0ef41Sopenharmony_ci  void Prologue();
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ci  // Helpers for argument handling
4341cb0ef41Sopenharmony_ci  enum ArgumentsCountMode { kCountIncludesReceiver, kCountExcludesReceiver };
4351cb0ef41Sopenharmony_ci  enum ArgumentsCountType { kCountIsInteger, kCountIsSmi, kCountIsBytes };
4361cb0ef41Sopenharmony_ci  void DropArguments(Register count, Register scratch, ArgumentsCountType type,
4371cb0ef41Sopenharmony_ci                     ArgumentsCountMode mode);
4381cb0ef41Sopenharmony_ci  void DropArgumentsAndPushNewReceiver(Register argc, Register receiver,
4391cb0ef41Sopenharmony_ci                                       Register scratch,
4401cb0ef41Sopenharmony_ci                                       ArgumentsCountType type,
4411cb0ef41Sopenharmony_ci                                       ArgumentsCountMode mode);
4421cb0ef41Sopenharmony_ci  void DropArgumentsAndPushNewReceiver(Register argc, Operand receiver,
4431cb0ef41Sopenharmony_ci                                       Register scratch,
4441cb0ef41Sopenharmony_ci                                       ArgumentsCountType type,
4451cb0ef41Sopenharmony_ci                                       ArgumentsCountMode mode);
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_ci  // Calls Abort(msg) if the condition cc is not satisfied.
4481cb0ef41Sopenharmony_ci  // Use --debug_code to enable.
4491cb0ef41Sopenharmony_ci  void Assert(Condition cc, AbortReason reason);
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_ci  // Like Assert(), but without condition.
4521cb0ef41Sopenharmony_ci  // Use --debug_code to enable.
4531cb0ef41Sopenharmony_ci  void AssertUnreachable(AbortReason reason);
4541cb0ef41Sopenharmony_ci
4551cb0ef41Sopenharmony_ci  // Abort execution if a 64 bit register containing a 32 bit payload does not
4561cb0ef41Sopenharmony_ci  // have zeros in the top 32 bits, enabled via --debug-code.
4571cb0ef41Sopenharmony_ci  void AssertZeroExtended(Register reg);
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci  // Like Assert(), but always enabled.
4601cb0ef41Sopenharmony_ci  void Check(Condition cc, AbortReason reason);
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ci  // Print a message to stdout and abort execution.
4631cb0ef41Sopenharmony_ci  void Abort(AbortReason msg);
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci  // Check that the stack is aligned.
4661cb0ef41Sopenharmony_ci  void CheckStackAlignment();
4671cb0ef41Sopenharmony_ci
4681cb0ef41Sopenharmony_ci  // Activation support.
4691cb0ef41Sopenharmony_ci  void EnterFrame(StackFrame::Type type);
4701cb0ef41Sopenharmony_ci  void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg) {
4711cb0ef41Sopenharmony_ci    // Out-of-line constant pool not implemented on x64.
4721cb0ef41Sopenharmony_ci    UNREACHABLE();
4731cb0ef41Sopenharmony_ci  }
4741cb0ef41Sopenharmony_ci  void LeaveFrame(StackFrame::Type type);
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ci// Allocate stack space of given size (i.e. decrement {rsp} by the value
4771cb0ef41Sopenharmony_ci// stored in the given register, or by a constant). If you need to perform a
4781cb0ef41Sopenharmony_ci// stack check, do it before calling this function because this function may
4791cb0ef41Sopenharmony_ci// write into the newly allocated space. It may also overwrite the given
4801cb0ef41Sopenharmony_ci// register's value, in the version that takes a register.
4811cb0ef41Sopenharmony_ci#if defined(V8_TARGET_OS_WIN) || defined(V8_TARGET_OS_MACOS)
4821cb0ef41Sopenharmony_ci  void AllocateStackSpace(Register bytes_scratch);
4831cb0ef41Sopenharmony_ci  void AllocateStackSpace(int bytes);
4841cb0ef41Sopenharmony_ci#else
4851cb0ef41Sopenharmony_ci  void AllocateStackSpace(Register bytes) { subq(rsp, bytes); }
4861cb0ef41Sopenharmony_ci  void AllocateStackSpace(int bytes) {
4871cb0ef41Sopenharmony_ci    DCHECK_GE(bytes, 0);
4881cb0ef41Sopenharmony_ci    if (bytes == 0) return;
4891cb0ef41Sopenharmony_ci    subq(rsp, Immediate(bytes));
4901cb0ef41Sopenharmony_ci  }
4911cb0ef41Sopenharmony_ci#endif
4921cb0ef41Sopenharmony_ci
4931cb0ef41Sopenharmony_ci  void InitializeRootRegister() {
4941cb0ef41Sopenharmony_ci    ExternalReference isolate_root = ExternalReference::isolate_root(isolate());
4951cb0ef41Sopenharmony_ci    Move(kRootRegister, isolate_root);
4961cb0ef41Sopenharmony_ci#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE
4971cb0ef41Sopenharmony_ci    LoadRootRelative(kPtrComprCageBaseRegister,
4981cb0ef41Sopenharmony_ci                     IsolateData::cage_base_offset());
4991cb0ef41Sopenharmony_ci#endif
5001cb0ef41Sopenharmony_ci  }
5011cb0ef41Sopenharmony_ci
5021cb0ef41Sopenharmony_ci  void MaybeSaveRegisters(RegList registers);
5031cb0ef41Sopenharmony_ci  void MaybeRestoreRegisters(RegList registers);
5041cb0ef41Sopenharmony_ci
5051cb0ef41Sopenharmony_ci  void CallEphemeronKeyBarrier(Register object, Register slot_address,
5061cb0ef41Sopenharmony_ci                               SaveFPRegsMode fp_mode);
5071cb0ef41Sopenharmony_ci
5081cb0ef41Sopenharmony_ci  void CallRecordWriteStubSaveRegisters(
5091cb0ef41Sopenharmony_ci      Register object, Register slot_address,
5101cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
5111cb0ef41Sopenharmony_ci      StubCallMode mode = StubCallMode::kCallBuiltinPointer);
5121cb0ef41Sopenharmony_ci  void CallRecordWriteStub(
5131cb0ef41Sopenharmony_ci      Register object, Register slot_address,
5141cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
5151cb0ef41Sopenharmony_ci      StubCallMode mode = StubCallMode::kCallBuiltinPointer);
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_ci#ifdef V8_IS_TSAN
5181cb0ef41Sopenharmony_ci  void CallTSANStoreStub(Register address, Register value,
5191cb0ef41Sopenharmony_ci                         SaveFPRegsMode fp_mode, int size, StubCallMode mode,
5201cb0ef41Sopenharmony_ci                         std::memory_order order);
5211cb0ef41Sopenharmony_ci  void CallTSANRelaxedLoadStub(Register address, SaveFPRegsMode fp_mode,
5221cb0ef41Sopenharmony_ci                               int size, StubCallMode mode);
5231cb0ef41Sopenharmony_ci#endif  // V8_IS_TSAN
5241cb0ef41Sopenharmony_ci
5251cb0ef41Sopenharmony_ci  void MoveNumber(Register dst, double value);
5261cb0ef41Sopenharmony_ci  void MoveNonSmi(Register dst, double value);
5271cb0ef41Sopenharmony_ci
5281cb0ef41Sopenharmony_ci  // Calculate how much stack space (in bytes) are required to store caller
5291cb0ef41Sopenharmony_ci  // registers excluding those specified in the arguments.
5301cb0ef41Sopenharmony_ci  int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
5311cb0ef41Sopenharmony_ci                                      Register exclusion1 = no_reg,
5321cb0ef41Sopenharmony_ci                                      Register exclusion2 = no_reg,
5331cb0ef41Sopenharmony_ci                                      Register exclusion3 = no_reg) const;
5341cb0ef41Sopenharmony_ci
5351cb0ef41Sopenharmony_ci  // PushCallerSaved and PopCallerSaved do not arrange the registers in any
5361cb0ef41Sopenharmony_ci  // particular order so they are not useful for calls that can cause a GC.
5371cb0ef41Sopenharmony_ci  // The caller can exclude up to 3 registers that do not need to be saved and
5381cb0ef41Sopenharmony_ci  // restored.
5391cb0ef41Sopenharmony_ci
5401cb0ef41Sopenharmony_ci  // Push caller saved registers on the stack, and return the number of bytes
5411cb0ef41Sopenharmony_ci  // stack pointer is adjusted.
5421cb0ef41Sopenharmony_ci  int PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
5431cb0ef41Sopenharmony_ci                      Register exclusion2 = no_reg,
5441cb0ef41Sopenharmony_ci                      Register exclusion3 = no_reg);
5451cb0ef41Sopenharmony_ci  // Restore caller saved registers from the stack, and return the number of
5461cb0ef41Sopenharmony_ci  // bytes stack pointer is adjusted.
5471cb0ef41Sopenharmony_ci  int PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
5481cb0ef41Sopenharmony_ci                     Register exclusion2 = no_reg,
5491cb0ef41Sopenharmony_ci                     Register exclusion3 = no_reg);
5501cb0ef41Sopenharmony_ci
5511cb0ef41Sopenharmony_ci  // Compute the start of the generated instruction stream from the current PC.
5521cb0ef41Sopenharmony_ci  // This is an alternative to embedding the {CodeObject} handle as a reference.
5531cb0ef41Sopenharmony_ci  void ComputeCodeStartAddress(Register dst);
5541cb0ef41Sopenharmony_ci
5551cb0ef41Sopenharmony_ci  // Control-flow integrity:
5561cb0ef41Sopenharmony_ci
5571cb0ef41Sopenharmony_ci  // Define a function entrypoint. This doesn't emit any code for this
5581cb0ef41Sopenharmony_ci  // architecture, as control-flow integrity is not supported for it.
5591cb0ef41Sopenharmony_ci  void CodeEntry() {}
5601cb0ef41Sopenharmony_ci  // Define an exception handler.
5611cb0ef41Sopenharmony_ci  void ExceptionHandler() {}
5621cb0ef41Sopenharmony_ci  // Define an exception handler and bind a label.
5631cb0ef41Sopenharmony_ci  void BindExceptionHandler(Label* label) { bind(label); }
5641cb0ef41Sopenharmony_ci
5651cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
5661cb0ef41Sopenharmony_ci  // Pointer compression support
5671cb0ef41Sopenharmony_ci
5681cb0ef41Sopenharmony_ci  // Loads a field containing a HeapObject and decompresses it if pointer
5691cb0ef41Sopenharmony_ci  // compression is enabled.
5701cb0ef41Sopenharmony_ci  void LoadTaggedPointerField(Register destination, Operand field_operand);
5711cb0ef41Sopenharmony_ci
5721cb0ef41Sopenharmony_ci  // Loads a field containing a Smi and decompresses it if pointer compression
5731cb0ef41Sopenharmony_ci  // is enabled.
5741cb0ef41Sopenharmony_ci  void LoadTaggedSignedField(Register destination, Operand field_operand);
5751cb0ef41Sopenharmony_ci
5761cb0ef41Sopenharmony_ci  // Loads a field containing any tagged value and decompresses it if necessary.
5771cb0ef41Sopenharmony_ci  void LoadAnyTaggedField(Register destination, Operand field_operand);
5781cb0ef41Sopenharmony_ci
5791cb0ef41Sopenharmony_ci  // Loads a field containing a HeapObject, decompresses it if necessary and
5801cb0ef41Sopenharmony_ci  // pushes full pointer to the stack. When pointer compression is enabled,
5811cb0ef41Sopenharmony_ci  // uses |scratch| to decompress the value.
5821cb0ef41Sopenharmony_ci  void PushTaggedPointerField(Operand field_operand, Register scratch);
5831cb0ef41Sopenharmony_ci
5841cb0ef41Sopenharmony_ci  // Loads a field containing any tagged value, decompresses it if necessary and
5851cb0ef41Sopenharmony_ci  // pushes the full pointer to the stack. When pointer compression is enabled,
5861cb0ef41Sopenharmony_ci  // uses |scratch| to decompress the value.
5871cb0ef41Sopenharmony_ci  void PushTaggedAnyField(Operand field_operand, Register scratch);
5881cb0ef41Sopenharmony_ci
5891cb0ef41Sopenharmony_ci  // Loads a field containing smi value and untags it.
5901cb0ef41Sopenharmony_ci  void SmiUntagField(Register dst, Operand src);
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_ci  // Compresses tagged value if necessary and stores it to given on-heap
5931cb0ef41Sopenharmony_ci  // location.
5941cb0ef41Sopenharmony_ci  void StoreTaggedField(Operand dst_field_operand, Immediate immediate);
5951cb0ef41Sopenharmony_ci  void StoreTaggedField(Operand dst_field_operand, Register value);
5961cb0ef41Sopenharmony_ci  void StoreTaggedSignedField(Operand dst_field_operand, Smi value);
5971cb0ef41Sopenharmony_ci  void AtomicStoreTaggedField(Operand dst_field_operand, Register value);
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci  // The following macros work even when pointer compression is not enabled.
6001cb0ef41Sopenharmony_ci  void DecompressTaggedSigned(Register destination, Operand field_operand);
6011cb0ef41Sopenharmony_ci  void DecompressTaggedPointer(Register destination, Operand field_operand);
6021cb0ef41Sopenharmony_ci  void DecompressTaggedPointer(Register destination, Register source);
6031cb0ef41Sopenharmony_ci  void DecompressAnyTagged(Register destination, Operand field_operand);
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
6061cb0ef41Sopenharmony_ci  // V8 Sandbox support
6071cb0ef41Sopenharmony_ci
6081cb0ef41Sopenharmony_ci  // Transform a SandboxedPointer from/to its encoded form, which is used when
6091cb0ef41Sopenharmony_ci  // the pointer is stored on the heap and ensures that the pointer will always
6101cb0ef41Sopenharmony_ci  // point into the sandbox.
6111cb0ef41Sopenharmony_ci  void EncodeSandboxedPointer(Register value);
6121cb0ef41Sopenharmony_ci  void DecodeSandboxedPointer(Register value);
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci  // Load and decode a SandboxedPointer from the heap.
6151cb0ef41Sopenharmony_ci  void LoadSandboxedPointerField(Register destination, Operand field_operand);
6161cb0ef41Sopenharmony_ci  // Encode and store a SandboxedPointer to the heap.
6171cb0ef41Sopenharmony_ci  void StoreSandboxedPointerField(Operand dst_field_operand, Register value);
6181cb0ef41Sopenharmony_ci
6191cb0ef41Sopenharmony_ci  enum class IsolateRootLocation { kInScratchRegister, kInRootRegister };
6201cb0ef41Sopenharmony_ci  // Loads a field containing off-heap pointer and does necessary decoding
6211cb0ef41Sopenharmony_ci  // if sandboxed external pointers are enabled.
6221cb0ef41Sopenharmony_ci  void LoadExternalPointerField(Register destination, Operand field_operand,
6231cb0ef41Sopenharmony_ci                                ExternalPointerTag tag, Register scratch,
6241cb0ef41Sopenharmony_ci                                IsolateRootLocation isolateRootLocation =
6251cb0ef41Sopenharmony_ci                                    IsolateRootLocation::kInRootRegister);
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_ci protected:
6281cb0ef41Sopenharmony_ci  static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ci  // Returns a register holding the smi value. The register MUST NOT be
6311cb0ef41Sopenharmony_ci  // modified. It may be the "smi 1 constant" register.
6321cb0ef41Sopenharmony_ci  Register GetSmiConstant(Smi value);
6331cb0ef41Sopenharmony_ci
6341cb0ef41Sopenharmony_ci  // Drops arguments assuming that the return address was already popped.
6351cb0ef41Sopenharmony_ci  void DropArguments(Register count, ArgumentsCountType type = kCountIsInteger,
6361cb0ef41Sopenharmony_ci                     ArgumentsCountMode mode = kCountExcludesReceiver);
6371cb0ef41Sopenharmony_ci};
6381cb0ef41Sopenharmony_ci
6391cb0ef41Sopenharmony_ci// MacroAssembler implements a collection of frequently used macros.
6401cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
6411cb0ef41Sopenharmony_ci public:
6421cb0ef41Sopenharmony_ci  using TurboAssembler::TurboAssembler;
6431cb0ef41Sopenharmony_ci
6441cb0ef41Sopenharmony_ci  // Loads and stores the value of an external reference.
6451cb0ef41Sopenharmony_ci  // Special case code for load and store to take advantage of
6461cb0ef41Sopenharmony_ci  // load_rax/store_rax if possible/necessary.
6471cb0ef41Sopenharmony_ci  // For other operations, just use:
6481cb0ef41Sopenharmony_ci  //   Operand operand = ExternalReferenceAsOperand(extref);
6491cb0ef41Sopenharmony_ci  //   operation(operand, ..);
6501cb0ef41Sopenharmony_ci  void Load(Register destination, ExternalReference source);
6511cb0ef41Sopenharmony_ci  void Store(ExternalReference destination, Register source);
6521cb0ef41Sopenharmony_ci
6531cb0ef41Sopenharmony_ci  // Pushes the address of the external reference onto the stack.
6541cb0ef41Sopenharmony_ci  void PushAddress(ExternalReference source);
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ci  // Operations on roots in the root-array.
6571cb0ef41Sopenharmony_ci  // Load a root value where the index (or part of it) is variable.
6581cb0ef41Sopenharmony_ci  // The variable_offset register is added to the fixed_offset value
6591cb0ef41Sopenharmony_ci  // to get the index into the root-array.
6601cb0ef41Sopenharmony_ci  void PushRoot(RootIndex index);
6611cb0ef41Sopenharmony_ci
6621cb0ef41Sopenharmony_ci  // Compare the object in a register to a value and jump if they are equal.
6631cb0ef41Sopenharmony_ci  void JumpIfRoot(Register with, RootIndex index, Label* if_equal,
6641cb0ef41Sopenharmony_ci                  Label::Distance if_equal_distance = Label::kFar) {
6651cb0ef41Sopenharmony_ci    CompareRoot(with, index);
6661cb0ef41Sopenharmony_ci    j(equal, if_equal, if_equal_distance);
6671cb0ef41Sopenharmony_ci  }
6681cb0ef41Sopenharmony_ci  void JumpIfRoot(Operand with, RootIndex index, Label* if_equal,
6691cb0ef41Sopenharmony_ci                  Label::Distance if_equal_distance = Label::kFar) {
6701cb0ef41Sopenharmony_ci    CompareRoot(with, index);
6711cb0ef41Sopenharmony_ci    j(equal, if_equal, if_equal_distance);
6721cb0ef41Sopenharmony_ci  }
6731cb0ef41Sopenharmony_ci
6741cb0ef41Sopenharmony_ci  // Compare the object in a register to a value and jump if they are not equal.
6751cb0ef41Sopenharmony_ci  void JumpIfNotRoot(Register with, RootIndex index, Label* if_not_equal,
6761cb0ef41Sopenharmony_ci                     Label::Distance if_not_equal_distance = Label::kFar) {
6771cb0ef41Sopenharmony_ci    CompareRoot(with, index);
6781cb0ef41Sopenharmony_ci    j(not_equal, if_not_equal, if_not_equal_distance);
6791cb0ef41Sopenharmony_ci  }
6801cb0ef41Sopenharmony_ci  void JumpIfNotRoot(Operand with, RootIndex index, Label* if_not_equal,
6811cb0ef41Sopenharmony_ci                     Label::Distance if_not_equal_distance = Label::kFar) {
6821cb0ef41Sopenharmony_ci    CompareRoot(with, index);
6831cb0ef41Sopenharmony_ci    j(not_equal, if_not_equal, if_not_equal_distance);
6841cb0ef41Sopenharmony_ci  }
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
6871cb0ef41Sopenharmony_ci  // GC Support
6881cb0ef41Sopenharmony_ci
6891cb0ef41Sopenharmony_ci  // Notify the garbage collector that we wrote a pointer into an object.
6901cb0ef41Sopenharmony_ci  // |object| is the object being stored into, |value| is the object being
6911cb0ef41Sopenharmony_ci  // stored.  value and scratch registers are clobbered by the operation.
6921cb0ef41Sopenharmony_ci  // The offset is the offset from the start of the object, not the offset from
6931cb0ef41Sopenharmony_ci  // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
6941cb0ef41Sopenharmony_ci  void RecordWriteField(
6951cb0ef41Sopenharmony_ci      Register object, int offset, Register value, Register slot_address,
6961cb0ef41Sopenharmony_ci      SaveFPRegsMode save_fp,
6971cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action = RememberedSetAction::kEmit,
6981cb0ef41Sopenharmony_ci      SmiCheck smi_check = SmiCheck::kInline);
6991cb0ef41Sopenharmony_ci
7001cb0ef41Sopenharmony_ci  // For page containing |object| mark region covering |address|
7011cb0ef41Sopenharmony_ci  // dirty. |object| is the object being stored into, |value| is the
7021cb0ef41Sopenharmony_ci  // object being stored. The address and value registers are clobbered by the
7031cb0ef41Sopenharmony_ci  // operation.  RecordWrite filters out smis so it does not update
7041cb0ef41Sopenharmony_ci  // the write barrier if the value is a smi.
7051cb0ef41Sopenharmony_ci  void RecordWrite(
7061cb0ef41Sopenharmony_ci      Register object, Register slot_address, Register value,
7071cb0ef41Sopenharmony_ci      SaveFPRegsMode save_fp,
7081cb0ef41Sopenharmony_ci      RememberedSetAction remembered_set_action = RememberedSetAction::kEmit,
7091cb0ef41Sopenharmony_ci      SmiCheck smi_check = SmiCheck::kInline);
7101cb0ef41Sopenharmony_ci
7111cb0ef41Sopenharmony_ci  // Enter specific kind of exit frame; either in normal or
7121cb0ef41Sopenharmony_ci  // debug mode. Expects the number of arguments in register rax and
7131cb0ef41Sopenharmony_ci  // sets up the number of arguments in register rdi and the pointer
7141cb0ef41Sopenharmony_ci  // to the first argument in register rsi.
7151cb0ef41Sopenharmony_ci  //
7161cb0ef41Sopenharmony_ci  // Allocates arg_stack_space * kSystemPointerSize memory (not GCed) on the
7171cb0ef41Sopenharmony_ci  // stack accessible via StackSpaceOperand.
7181cb0ef41Sopenharmony_ci  void EnterExitFrame(int arg_stack_space = 0, bool save_doubles = false,
7191cb0ef41Sopenharmony_ci                      StackFrame::Type frame_type = StackFrame::EXIT);
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci  // Enter specific kind of exit frame. Allocates
7221cb0ef41Sopenharmony_ci  // (arg_stack_space * kSystemPointerSize) memory (not GCed) on the stack
7231cb0ef41Sopenharmony_ci  // accessible via StackSpaceOperand.
7241cb0ef41Sopenharmony_ci  void EnterApiExitFrame(int arg_stack_space);
7251cb0ef41Sopenharmony_ci
7261cb0ef41Sopenharmony_ci  // Leave the current exit frame. Expects/provides the return value in
7271cb0ef41Sopenharmony_ci  // register rax:rdx (untouched) and the pointer to the first
7281cb0ef41Sopenharmony_ci  // argument in register rsi (if pop_arguments == true).
7291cb0ef41Sopenharmony_ci  void LeaveExitFrame(bool save_doubles = false, bool pop_arguments = true);
7301cb0ef41Sopenharmony_ci
7311cb0ef41Sopenharmony_ci  // Leave the current exit frame. Expects/provides the return value in
7321cb0ef41Sopenharmony_ci  // register rax (untouched).
7331cb0ef41Sopenharmony_ci  void LeaveApiExitFrame();
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
7361cb0ef41Sopenharmony_ci  // JavaScript invokes
7371cb0ef41Sopenharmony_ci
7381cb0ef41Sopenharmony_ci  // Invoke the JavaScript function code by either calling or jumping.
7391cb0ef41Sopenharmony_ci  void InvokeFunctionCode(Register function, Register new_target,
7401cb0ef41Sopenharmony_ci                          Register expected_parameter_count,
7411cb0ef41Sopenharmony_ci                          Register actual_parameter_count, InvokeType type);
7421cb0ef41Sopenharmony_ci
7431cb0ef41Sopenharmony_ci  // On function call, call into the debugger.
7441cb0ef41Sopenharmony_ci  void CallDebugOnFunctionCall(Register fun, Register new_target,
7451cb0ef41Sopenharmony_ci                               Register expected_parameter_count,
7461cb0ef41Sopenharmony_ci                               Register actual_parameter_count);
7471cb0ef41Sopenharmony_ci
7481cb0ef41Sopenharmony_ci  // Invoke the JavaScript function in the given register. Changes the
7491cb0ef41Sopenharmony_ci  // current context to the context in the function before invoking.
7501cb0ef41Sopenharmony_ci  void InvokeFunction(Register function, Register new_target,
7511cb0ef41Sopenharmony_ci                      Register actual_parameter_count, InvokeType type);
7521cb0ef41Sopenharmony_ci
7531cb0ef41Sopenharmony_ci  void InvokeFunction(Register function, Register new_target,
7541cb0ef41Sopenharmony_ci                      Register expected_parameter_count,
7551cb0ef41Sopenharmony_ci                      Register actual_parameter_count, InvokeType type);
7561cb0ef41Sopenharmony_ci
7571cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
7581cb0ef41Sopenharmony_ci  // Macro instructions.
7591cb0ef41Sopenharmony_ci
7601cb0ef41Sopenharmony_ci  using TurboAssembler::Cmp;
7611cb0ef41Sopenharmony_ci  void Cmp(Register dst, Handle<Object> source);
7621cb0ef41Sopenharmony_ci  void Cmp(Operand dst, Handle<Object> source);
7631cb0ef41Sopenharmony_ci
7641cb0ef41Sopenharmony_ci  // Checks if value is in range [lower_limit, higher_limit] using a single
7651cb0ef41Sopenharmony_ci  // comparison. Flags CF=1 or ZF=1 indicate the value is in the range
7661cb0ef41Sopenharmony_ci  // (condition below_equal).
7671cb0ef41Sopenharmony_ci  void CompareRange(Register value, unsigned lower_limit,
7681cb0ef41Sopenharmony_ci                    unsigned higher_limit);
7691cb0ef41Sopenharmony_ci  void JumpIfIsInRange(Register value, unsigned lower_limit,
7701cb0ef41Sopenharmony_ci                       unsigned higher_limit, Label* on_in_range,
7711cb0ef41Sopenharmony_ci                       Label::Distance near_jump = Label::kFar);
7721cb0ef41Sopenharmony_ci
7731cb0ef41Sopenharmony_ci  // Emit code to discard a non-negative number of pointer-sized elements
7741cb0ef41Sopenharmony_ci  // from the stack, clobbering only the rsp register.
7751cb0ef41Sopenharmony_ci  void Drop(int stack_elements);
7761cb0ef41Sopenharmony_ci  // Emit code to discard a positive number of pointer-sized elements
7771cb0ef41Sopenharmony_ci  // from the stack under the return address which remains on the top,
7781cb0ef41Sopenharmony_ci  // clobbering the rsp register.
7791cb0ef41Sopenharmony_ci  void DropUnderReturnAddress(int stack_elements,
7801cb0ef41Sopenharmony_ci                              Register scratch = kScratchRegister);
7811cb0ef41Sopenharmony_ci  void PushQuad(Operand src);
7821cb0ef41Sopenharmony_ci  void PushImm32(int32_t imm32);
7831cb0ef41Sopenharmony_ci  void Pop(Register dst);
7841cb0ef41Sopenharmony_ci  void Pop(Operand dst);
7851cb0ef41Sopenharmony_ci  void PopQuad(Operand dst);
7861cb0ef41Sopenharmony_ci
7871cb0ef41Sopenharmony_ci  // Generates a trampoline to jump to the off-heap instruction stream.
7881cb0ef41Sopenharmony_ci  void JumpToOffHeapInstructionStream(Address entry);
7891cb0ef41Sopenharmony_ci
7901cb0ef41Sopenharmony_ci  // Compare object type for heap object.
7911cb0ef41Sopenharmony_ci  // Always use unsigned comparisons: above and below, not less and greater.
7921cb0ef41Sopenharmony_ci  // Incoming register is heap_object and outgoing register is map.
7931cb0ef41Sopenharmony_ci  // They may be the same register, and may be kScratchRegister.
7941cb0ef41Sopenharmony_ci  void CmpObjectType(Register heap_object, InstanceType type, Register map);
7951cb0ef41Sopenharmony_ci
7961cb0ef41Sopenharmony_ci  // Compare instance type for map.
7971cb0ef41Sopenharmony_ci  // Always use unsigned comparisons: above and below, not less and greater.
7981cb0ef41Sopenharmony_ci  void CmpInstanceType(Register map, InstanceType type);
7991cb0ef41Sopenharmony_ci
8001cb0ef41Sopenharmony_ci  // Compare instance type ranges for a map (low and high inclusive)
8011cb0ef41Sopenharmony_ci  // Always use unsigned comparisons: below_equal for a positive result.
8021cb0ef41Sopenharmony_ci  void CmpInstanceTypeRange(Register map, Register instance_type_out,
8031cb0ef41Sopenharmony_ci                            InstanceType low, InstanceType high);
8041cb0ef41Sopenharmony_ci
8051cb0ef41Sopenharmony_ci  template <typename Field>
8061cb0ef41Sopenharmony_ci  void DecodeField(Register reg) {
8071cb0ef41Sopenharmony_ci    static const int shift = Field::kShift;
8081cb0ef41Sopenharmony_ci    static const int mask = Field::kMask >> Field::kShift;
8091cb0ef41Sopenharmony_ci    if (shift != 0) {
8101cb0ef41Sopenharmony_ci      shrq(reg, Immediate(shift));
8111cb0ef41Sopenharmony_ci    }
8121cb0ef41Sopenharmony_ci    andq(reg, Immediate(mask));
8131cb0ef41Sopenharmony_ci  }
8141cb0ef41Sopenharmony_ci
8151cb0ef41Sopenharmony_ci  // Abort execution if argument is not a CodeT, enabled via --debug-code.
8161cb0ef41Sopenharmony_ci  void AssertCodeT(Register object);
8171cb0ef41Sopenharmony_ci
8181cb0ef41Sopenharmony_ci  // Abort execution if argument is not a Constructor, enabled via --debug-code.
8191cb0ef41Sopenharmony_ci  void AssertConstructor(Register object);
8201cb0ef41Sopenharmony_ci
8211cb0ef41Sopenharmony_ci  // Abort execution if argument is not a JSFunction, enabled via --debug-code.
8221cb0ef41Sopenharmony_ci  void AssertFunction(Register object);
8231cb0ef41Sopenharmony_ci
8241cb0ef41Sopenharmony_ci  // Abort execution if argument is not a callable JSFunction, enabled via
8251cb0ef41Sopenharmony_ci  // --debug-code.
8261cb0ef41Sopenharmony_ci  void AssertCallableFunction(Register object);
8271cb0ef41Sopenharmony_ci
8281cb0ef41Sopenharmony_ci  // Abort execution if argument is not a JSBoundFunction,
8291cb0ef41Sopenharmony_ci  // enabled via --debug-code.
8301cb0ef41Sopenharmony_ci  void AssertBoundFunction(Register object);
8311cb0ef41Sopenharmony_ci
8321cb0ef41Sopenharmony_ci  // Abort execution if argument is not a JSGeneratorObject (or subclass),
8331cb0ef41Sopenharmony_ci  // enabled via --debug-code.
8341cb0ef41Sopenharmony_ci  void AssertGeneratorObject(Register object);
8351cb0ef41Sopenharmony_ci
8361cb0ef41Sopenharmony_ci  // Abort execution if argument is not undefined or an AllocationSite, enabled
8371cb0ef41Sopenharmony_ci  // via --debug-code.
8381cb0ef41Sopenharmony_ci  void AssertUndefinedOrAllocationSite(Register object);
8391cb0ef41Sopenharmony_ci
8401cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
8411cb0ef41Sopenharmony_ci  // Exception handling
8421cb0ef41Sopenharmony_ci
8431cb0ef41Sopenharmony_ci  // Push a new stack handler and link it into stack handler chain.
8441cb0ef41Sopenharmony_ci  void PushStackHandler();
8451cb0ef41Sopenharmony_ci
8461cb0ef41Sopenharmony_ci  // Unlink the stack handler on top of the stack from the stack handler chain.
8471cb0ef41Sopenharmony_ci  void PopStackHandler();
8481cb0ef41Sopenharmony_ci
8491cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
8501cb0ef41Sopenharmony_ci  // Support functions.
8511cb0ef41Sopenharmony_ci
8521cb0ef41Sopenharmony_ci  // Load the global proxy from the current context.
8531cb0ef41Sopenharmony_ci  void LoadGlobalProxy(Register dst) {
8541cb0ef41Sopenharmony_ci    LoadNativeContextSlot(dst, Context::GLOBAL_PROXY_INDEX);
8551cb0ef41Sopenharmony_ci  }
8561cb0ef41Sopenharmony_ci
8571cb0ef41Sopenharmony_ci  // Load the native context slot with the current index.
8581cb0ef41Sopenharmony_ci  void LoadNativeContextSlot(Register dst, int index);
8591cb0ef41Sopenharmony_ci
8601cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
8611cb0ef41Sopenharmony_ci  // Runtime calls
8621cb0ef41Sopenharmony_ci
8631cb0ef41Sopenharmony_ci  // Call a runtime routine.
8641cb0ef41Sopenharmony_ci  void CallRuntime(const Runtime::Function* f, int num_arguments,
8651cb0ef41Sopenharmony_ci                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore);
8661cb0ef41Sopenharmony_ci
8671cb0ef41Sopenharmony_ci  // Convenience function: Same as above, but takes the fid instead.
8681cb0ef41Sopenharmony_ci  void CallRuntime(Runtime::FunctionId fid,
8691cb0ef41Sopenharmony_ci                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) {
8701cb0ef41Sopenharmony_ci    const Runtime::Function* function = Runtime::FunctionForId(fid);
8711cb0ef41Sopenharmony_ci    CallRuntime(function, function->nargs, save_doubles);
8721cb0ef41Sopenharmony_ci  }
8731cb0ef41Sopenharmony_ci
8741cb0ef41Sopenharmony_ci  // Convenience function: Same as above, but takes the fid instead.
8751cb0ef41Sopenharmony_ci  void CallRuntime(Runtime::FunctionId fid, int num_arguments,
8761cb0ef41Sopenharmony_ci                   SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) {
8771cb0ef41Sopenharmony_ci    CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles);
8781cb0ef41Sopenharmony_ci  }
8791cb0ef41Sopenharmony_ci
8801cb0ef41Sopenharmony_ci  // Convenience function: tail call a runtime routine (jump)
8811cb0ef41Sopenharmony_ci  void TailCallRuntime(Runtime::FunctionId fid);
8821cb0ef41Sopenharmony_ci
8831cb0ef41Sopenharmony_ci  // Jump to a runtime routines
8841cb0ef41Sopenharmony_ci  void JumpToExternalReference(const ExternalReference& ext,
8851cb0ef41Sopenharmony_ci                               bool builtin_exit_frame = false);
8861cb0ef41Sopenharmony_ci
8871cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
8881cb0ef41Sopenharmony_ci  // StatsCounter support
8891cb0ef41Sopenharmony_ci  void IncrementCounter(StatsCounter* counter, int value) {
8901cb0ef41Sopenharmony_ci    if (!FLAG_native_code_counters) return;
8911cb0ef41Sopenharmony_ci    EmitIncrementCounter(counter, value);
8921cb0ef41Sopenharmony_ci  }
8931cb0ef41Sopenharmony_ci  void EmitIncrementCounter(StatsCounter* counter, int value);
8941cb0ef41Sopenharmony_ci  void DecrementCounter(StatsCounter* counter, int value) {
8951cb0ef41Sopenharmony_ci    if (!FLAG_native_code_counters) return;
8961cb0ef41Sopenharmony_ci    EmitDecrementCounter(counter, value);
8971cb0ef41Sopenharmony_ci  }
8981cb0ef41Sopenharmony_ci  void EmitDecrementCounter(StatsCounter* counter, int value);
8991cb0ef41Sopenharmony_ci
9001cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
9011cb0ef41Sopenharmony_ci  // Stack limit utilities
9021cb0ef41Sopenharmony_ci  Operand StackLimitAsOperand(StackLimitKind kind);
9031cb0ef41Sopenharmony_ci  void StackOverflowCheck(
9041cb0ef41Sopenharmony_ci      Register num_args, Label* stack_overflow,
9051cb0ef41Sopenharmony_ci      Label::Distance stack_overflow_distance = Label::kFar);
9061cb0ef41Sopenharmony_ci
9071cb0ef41Sopenharmony_ci  // ---------------------------------------------------------------------------
9081cb0ef41Sopenharmony_ci  // In-place weak references.
9091cb0ef41Sopenharmony_ci  void LoadWeakValue(Register in_out, Label* target_if_cleared);
9101cb0ef41Sopenharmony_ci
9111cb0ef41Sopenharmony_ci private:
9121cb0ef41Sopenharmony_ci  // Helper functions for generating invokes.
9131cb0ef41Sopenharmony_ci  void InvokePrologue(Register expected_parameter_count,
9141cb0ef41Sopenharmony_ci                      Register actual_parameter_count, Label* done,
9151cb0ef41Sopenharmony_ci                      InvokeType type);
9161cb0ef41Sopenharmony_ci
9171cb0ef41Sopenharmony_ci  void EnterExitFramePrologue(Register saved_rax_reg,
9181cb0ef41Sopenharmony_ci                              StackFrame::Type frame_type);
9191cb0ef41Sopenharmony_ci
9201cb0ef41Sopenharmony_ci  // Allocates arg_stack_space * kSystemPointerSize memory (not GCed) on the
9211cb0ef41Sopenharmony_ci  // stack accessible via StackSpaceOperand.
9221cb0ef41Sopenharmony_ci  void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles);
9231cb0ef41Sopenharmony_ci
9241cb0ef41Sopenharmony_ci  void LeaveExitFrameEpilogue();
9251cb0ef41Sopenharmony_ci
9261cb0ef41Sopenharmony_ci  DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler);
9271cb0ef41Sopenharmony_ci};
9281cb0ef41Sopenharmony_ci
9291cb0ef41Sopenharmony_ci// -----------------------------------------------------------------------------
9301cb0ef41Sopenharmony_ci// Static helper functions.
9311cb0ef41Sopenharmony_ci
9321cb0ef41Sopenharmony_ci// Generate an Operand for loading a field from an object.
9331cb0ef41Sopenharmony_ciinline Operand FieldOperand(Register object, int offset) {
9341cb0ef41Sopenharmony_ci  return Operand(object, offset - kHeapObjectTag);
9351cb0ef41Sopenharmony_ci}
9361cb0ef41Sopenharmony_ci
9371cb0ef41Sopenharmony_ci// Generate an Operand for loading an indexed field from an object.
9381cb0ef41Sopenharmony_ciinline Operand FieldOperand(Register object, Register index, ScaleFactor scale,
9391cb0ef41Sopenharmony_ci                            int offset) {
9401cb0ef41Sopenharmony_ci  return Operand(object, index, scale, offset - kHeapObjectTag);
9411cb0ef41Sopenharmony_ci}
9421cb0ef41Sopenharmony_ci
9431cb0ef41Sopenharmony_ci// Provides access to exit frame stack space (not GCed).
9441cb0ef41Sopenharmony_ciinline Operand StackSpaceOperand(int index) {
9451cb0ef41Sopenharmony_ci#ifdef V8_TARGET_OS_WIN
9461cb0ef41Sopenharmony_ci  const int kShaddowSpace = 4;
9471cb0ef41Sopenharmony_ci  return Operand(rsp, (index + kShaddowSpace) * kSystemPointerSize);
9481cb0ef41Sopenharmony_ci#else
9491cb0ef41Sopenharmony_ci  return Operand(rsp, index * kSystemPointerSize);
9501cb0ef41Sopenharmony_ci#endif
9511cb0ef41Sopenharmony_ci}
9521cb0ef41Sopenharmony_ci
9531cb0ef41Sopenharmony_ciinline Operand StackOperandForReturnAddress(int32_t disp) {
9541cb0ef41Sopenharmony_ci  return Operand(rsp, disp);
9551cb0ef41Sopenharmony_ci}
9561cb0ef41Sopenharmony_ci
9571cb0ef41Sopenharmony_ci#define ACCESS_MASM(masm) masm->
9581cb0ef41Sopenharmony_ci
9591cb0ef41Sopenharmony_ci}  // namespace internal
9601cb0ef41Sopenharmony_ci}  // namespace v8
9611cb0ef41Sopenharmony_ci
9621cb0ef41Sopenharmony_ci#endif  // V8_CODEGEN_X64_MACRO_ASSEMBLER_X64_H_
963