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#if V8_TARGET_ARCH_IA32
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <stdint.h>
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#include "include/v8-internal.h"
101cb0ef41Sopenharmony_ci#include "src/base/bits.h"
111cb0ef41Sopenharmony_ci#include "src/base/logging.h"
121cb0ef41Sopenharmony_ci#include "src/base/macros.h"
131cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h"
141cb0ef41Sopenharmony_ci#include "src/builtins/builtins.h"
151cb0ef41Sopenharmony_ci#include "src/codegen/assembler.h"
161cb0ef41Sopenharmony_ci#include "src/codegen/bailout-reason.h"
171cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h"
181cb0ef41Sopenharmony_ci#include "src/codegen/cpu-features.h"
191cb0ef41Sopenharmony_ci#include "src/codegen/external-reference.h"
201cb0ef41Sopenharmony_ci#include "src/codegen/ia32/assembler-ia32.h"
211cb0ef41Sopenharmony_ci#include "src/codegen/ia32/register-ia32.h"
221cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors-inl.h"
231cb0ef41Sopenharmony_ci#include "src/codegen/label.h"
241cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h"
251cb0ef41Sopenharmony_ci#include "src/codegen/register.h"
261cb0ef41Sopenharmony_ci#include "src/codegen/reglist.h"
271cb0ef41Sopenharmony_ci#include "src/codegen/reloc-info.h"
281cb0ef41Sopenharmony_ci#include "src/codegen/turbo-assembler.h"
291cb0ef41Sopenharmony_ci#include "src/common/globals.h"
301cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimizer.h"
311cb0ef41Sopenharmony_ci#include "src/execution/frame-constants.h"
321cb0ef41Sopenharmony_ci#include "src/execution/frames.h"
331cb0ef41Sopenharmony_ci#include "src/execution/isolate-data.h"
341cb0ef41Sopenharmony_ci#include "src/execution/isolate.h"
351cb0ef41Sopenharmony_ci#include "src/flags/flags.h"
361cb0ef41Sopenharmony_ci#include "src/handles/handles-inl.h"
371cb0ef41Sopenharmony_ci#include "src/handles/handles.h"
381cb0ef41Sopenharmony_ci#include "src/heap/basic-memory-chunk.h"
391cb0ef41Sopenharmony_ci#include "src/heap/factory-inl.h"
401cb0ef41Sopenharmony_ci#include "src/heap/factory.h"
411cb0ef41Sopenharmony_ci#include "src/heap/memory-chunk.h"
421cb0ef41Sopenharmony_ci#include "src/logging/counters.h"
431cb0ef41Sopenharmony_ci#include "src/objects/code.h"
441cb0ef41Sopenharmony_ci#include "src/objects/contexts.h"
451cb0ef41Sopenharmony_ci#include "src/objects/fixed-array.h"
461cb0ef41Sopenharmony_ci#include "src/objects/heap-object.h"
471cb0ef41Sopenharmony_ci#include "src/objects/js-function.h"
481cb0ef41Sopenharmony_ci#include "src/objects/map.h"
491cb0ef41Sopenharmony_ci#include "src/objects/objects.h"
501cb0ef41Sopenharmony_ci#include "src/objects/oddball.h"
511cb0ef41Sopenharmony_ci#include "src/objects/shared-function-info.h"
521cb0ef41Sopenharmony_ci#include "src/objects/slots-inl.h"
531cb0ef41Sopenharmony_ci#include "src/objects/smi.h"
541cb0ef41Sopenharmony_ci#include "src/roots/roots-inl.h"
551cb0ef41Sopenharmony_ci#include "src/roots/roots.h"
561cb0ef41Sopenharmony_ci#include "src/runtime/runtime.h"
571cb0ef41Sopenharmony_ci#include "src/utils/utils.h"
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci// Satisfy cpplint check, but don't include platform-specific header. It is
601cb0ef41Sopenharmony_ci// included recursively via macro-assembler.h.
611cb0ef41Sopenharmony_ci#if 0
621cb0ef41Sopenharmony_ci#include "src/codegen/ia32/macro-assembler-ia32.h"
631cb0ef41Sopenharmony_ci#endif
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_cinamespace v8 {
661cb0ef41Sopenharmony_cinamespace internal {
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ciOperand StackArgumentsAccessor::GetArgumentOperand(int index) const {
691cb0ef41Sopenharmony_ci  DCHECK_GE(index, 0);
701cb0ef41Sopenharmony_ci  // arg[0] = esp + kPCOnStackSize;
711cb0ef41Sopenharmony_ci  // arg[i] = arg[0] + i * kSystemPointerSize;
721cb0ef41Sopenharmony_ci  return Operand(esp, kPCOnStackSize + index * kSystemPointerSize);
731cb0ef41Sopenharmony_ci}
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci// -------------------------------------------------------------------------
761cb0ef41Sopenharmony_ci// MacroAssembler implementation.
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_civoid TurboAssembler::InitializeRootRegister() {
791cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
801cb0ef41Sopenharmony_ci  ExternalReference isolate_root = ExternalReference::isolate_root(isolate());
811cb0ef41Sopenharmony_ci  Move(kRootRegister, Immediate(isolate_root));
821cb0ef41Sopenharmony_ci}
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ciOperand TurboAssembler::RootAsOperand(RootIndex index) {
851cb0ef41Sopenharmony_ci  DCHECK(root_array_available());
861cb0ef41Sopenharmony_ci  return Operand(kRootRegister, RootRegisterOffsetForRootIndex(index));
871cb0ef41Sopenharmony_ci}
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_civoid TurboAssembler::LoadRoot(Register destination, RootIndex index) {
901cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
911cb0ef41Sopenharmony_ci  if (root_array_available()) {
921cb0ef41Sopenharmony_ci    mov(destination, RootAsOperand(index));
931cb0ef41Sopenharmony_ci    return;
941cb0ef41Sopenharmony_ci  }
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  if (RootsTable::IsImmortalImmovable(index)) {
971cb0ef41Sopenharmony_ci    Handle<Object> object = isolate()->root_handle(index);
981cb0ef41Sopenharmony_ci    if (object->IsSmi()) {
991cb0ef41Sopenharmony_ci      mov(destination, Immediate(Smi::cast(*object)));
1001cb0ef41Sopenharmony_ci      return;
1011cb0ef41Sopenharmony_ci    } else {
1021cb0ef41Sopenharmony_ci      DCHECK(object->IsHeapObject());
1031cb0ef41Sopenharmony_ci      mov(destination, Handle<HeapObject>::cast(object));
1041cb0ef41Sopenharmony_ci      return;
1051cb0ef41Sopenharmony_ci    }
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  ExternalReference isolate_root = ExternalReference::isolate_root(isolate());
1091cb0ef41Sopenharmony_ci  lea(destination,
1101cb0ef41Sopenharmony_ci      Operand(isolate_root.address(), RelocInfo::EXTERNAL_REFERENCE));
1111cb0ef41Sopenharmony_ci  mov(destination, Operand(destination, RootRegisterOffsetForRootIndex(index)));
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_civoid TurboAssembler::CompareRoot(Register with, Register scratch,
1151cb0ef41Sopenharmony_ci                                 RootIndex index) {
1161cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
1171cb0ef41Sopenharmony_ci  if (root_array_available()) {
1181cb0ef41Sopenharmony_ci    CompareRoot(with, index);
1191cb0ef41Sopenharmony_ci  } else {
1201cb0ef41Sopenharmony_ci    ExternalReference isolate_root = ExternalReference::isolate_root(isolate());
1211cb0ef41Sopenharmony_ci    lea(scratch,
1221cb0ef41Sopenharmony_ci        Operand(isolate_root.address(), RelocInfo::EXTERNAL_REFERENCE));
1231cb0ef41Sopenharmony_ci    cmp(with, Operand(scratch, RootRegisterOffsetForRootIndex(index)));
1241cb0ef41Sopenharmony_ci  }
1251cb0ef41Sopenharmony_ci}
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_civoid TurboAssembler::CompareRoot(Register with, RootIndex index) {
1281cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
1291cb0ef41Sopenharmony_ci  if (root_array_available()) {
1301cb0ef41Sopenharmony_ci    cmp(with, RootAsOperand(index));
1311cb0ef41Sopenharmony_ci    return;
1321cb0ef41Sopenharmony_ci  }
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci  DCHECK(RootsTable::IsImmortalImmovable(index));
1351cb0ef41Sopenharmony_ci  Handle<Object> object = isolate()->root_handle(index);
1361cb0ef41Sopenharmony_ci  if (object->IsHeapObject()) {
1371cb0ef41Sopenharmony_ci    cmp(with, Handle<HeapObject>::cast(object));
1381cb0ef41Sopenharmony_ci  } else {
1391cb0ef41Sopenharmony_ci    cmp(with, Immediate(Smi::cast(*object)));
1401cb0ef41Sopenharmony_ci  }
1411cb0ef41Sopenharmony_ci}
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_civoid MacroAssembler::PushRoot(RootIndex index) {
1441cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
1451cb0ef41Sopenharmony_ci  if (root_array_available()) {
1461cb0ef41Sopenharmony_ci    DCHECK(RootsTable::IsImmortalImmovable(index));
1471cb0ef41Sopenharmony_ci    push(RootAsOperand(index));
1481cb0ef41Sopenharmony_ci    return;
1491cb0ef41Sopenharmony_ci  }
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  // TODO(v8:6666): Add a scratch register or remove all uses.
1521cb0ef41Sopenharmony_ci  DCHECK(RootsTable::IsImmortalImmovable(index));
1531cb0ef41Sopenharmony_ci  Handle<Object> object = isolate()->root_handle(index);
1541cb0ef41Sopenharmony_ci  if (object->IsHeapObject()) {
1551cb0ef41Sopenharmony_ci    Push(Handle<HeapObject>::cast(object));
1561cb0ef41Sopenharmony_ci  } else {
1571cb0ef41Sopenharmony_ci    Push(Smi::cast(*object));
1581cb0ef41Sopenharmony_ci  }
1591cb0ef41Sopenharmony_ci}
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_civoid MacroAssembler::CompareRange(Register value, unsigned lower_limit,
1621cb0ef41Sopenharmony_ci                                  unsigned higher_limit, Register scratch) {
1631cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
1641cb0ef41Sopenharmony_ci  DCHECK_LT(lower_limit, higher_limit);
1651cb0ef41Sopenharmony_ci  if (lower_limit != 0) {
1661cb0ef41Sopenharmony_ci    lea(scratch, Operand(value, 0u - lower_limit));
1671cb0ef41Sopenharmony_ci    cmp(scratch, Immediate(higher_limit - lower_limit));
1681cb0ef41Sopenharmony_ci  } else {
1691cb0ef41Sopenharmony_ci    cmp(value, Immediate(higher_limit));
1701cb0ef41Sopenharmony_ci  }
1711cb0ef41Sopenharmony_ci}
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_civoid MacroAssembler::JumpIfIsInRange(Register value, unsigned lower_limit,
1741cb0ef41Sopenharmony_ci                                     unsigned higher_limit, Register scratch,
1751cb0ef41Sopenharmony_ci                                     Label* on_in_range,
1761cb0ef41Sopenharmony_ci                                     Label::Distance near_jump) {
1771cb0ef41Sopenharmony_ci  CompareRange(value, lower_limit, higher_limit, scratch);
1781cb0ef41Sopenharmony_ci  j(below_equal, on_in_range, near_jump);
1791cb0ef41Sopenharmony_ci}
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_civoid TurboAssembler::PushArray(Register array, Register size, Register scratch,
1821cb0ef41Sopenharmony_ci                               PushArrayOrder order) {
1831cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
1841cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(array, size, scratch));
1851cb0ef41Sopenharmony_ci  Register counter = scratch;
1861cb0ef41Sopenharmony_ci  Label loop, entry;
1871cb0ef41Sopenharmony_ci  if (order == PushArrayOrder::kReverse) {
1881cb0ef41Sopenharmony_ci    mov(counter, 0);
1891cb0ef41Sopenharmony_ci    jmp(&entry);
1901cb0ef41Sopenharmony_ci    bind(&loop);
1911cb0ef41Sopenharmony_ci    Push(Operand(array, counter, times_system_pointer_size, 0));
1921cb0ef41Sopenharmony_ci    inc(counter);
1931cb0ef41Sopenharmony_ci    bind(&entry);
1941cb0ef41Sopenharmony_ci    cmp(counter, size);
1951cb0ef41Sopenharmony_ci    j(less, &loop, Label::kNear);
1961cb0ef41Sopenharmony_ci  } else {
1971cb0ef41Sopenharmony_ci    mov(counter, size);
1981cb0ef41Sopenharmony_ci    jmp(&entry);
1991cb0ef41Sopenharmony_ci    bind(&loop);
2001cb0ef41Sopenharmony_ci    Push(Operand(array, counter, times_system_pointer_size, 0));
2011cb0ef41Sopenharmony_ci    bind(&entry);
2021cb0ef41Sopenharmony_ci    dec(counter);
2031cb0ef41Sopenharmony_ci    j(greater_equal, &loop, Label::kNear);
2041cb0ef41Sopenharmony_ci  }
2051cb0ef41Sopenharmony_ci}
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ciOperand TurboAssembler::ExternalReferenceAsOperand(ExternalReference reference,
2081cb0ef41Sopenharmony_ci                                                   Register scratch) {
2091cb0ef41Sopenharmony_ci  if (root_array_available() && options().enable_root_relative_access) {
2101cb0ef41Sopenharmony_ci    intptr_t delta =
2111cb0ef41Sopenharmony_ci        RootRegisterOffsetForExternalReference(isolate(), reference);
2121cb0ef41Sopenharmony_ci    return Operand(kRootRegister, delta);
2131cb0ef41Sopenharmony_ci  }
2141cb0ef41Sopenharmony_ci  if (root_array_available() && options().isolate_independent_code) {
2151cb0ef41Sopenharmony_ci    if (IsAddressableThroughRootRegister(isolate(), reference)) {
2161cb0ef41Sopenharmony_ci      // Some external references can be efficiently loaded as an offset from
2171cb0ef41Sopenharmony_ci      // kRootRegister.
2181cb0ef41Sopenharmony_ci      intptr_t offset =
2191cb0ef41Sopenharmony_ci          RootRegisterOffsetForExternalReference(isolate(), reference);
2201cb0ef41Sopenharmony_ci      return Operand(kRootRegister, offset);
2211cb0ef41Sopenharmony_ci    } else {
2221cb0ef41Sopenharmony_ci      // Otherwise, do a memory load from the external reference table.
2231cb0ef41Sopenharmony_ci      mov(scratch, Operand(kRootRegister,
2241cb0ef41Sopenharmony_ci                           RootRegisterOffsetForExternalReferenceTableEntry(
2251cb0ef41Sopenharmony_ci                               isolate(), reference)));
2261cb0ef41Sopenharmony_ci      return Operand(scratch, 0);
2271cb0ef41Sopenharmony_ci    }
2281cb0ef41Sopenharmony_ci  }
2291cb0ef41Sopenharmony_ci  Move(scratch, Immediate(reference));
2301cb0ef41Sopenharmony_ci  return Operand(scratch, 0);
2311cb0ef41Sopenharmony_ci}
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci// TODO(v8:6666): If possible, refactor into a platform-independent function in
2341cb0ef41Sopenharmony_ci// TurboAssembler.
2351cb0ef41Sopenharmony_ciOperand TurboAssembler::ExternalReferenceAddressAsOperand(
2361cb0ef41Sopenharmony_ci    ExternalReference reference) {
2371cb0ef41Sopenharmony_ci  DCHECK(root_array_available());
2381cb0ef41Sopenharmony_ci  DCHECK(options().isolate_independent_code);
2391cb0ef41Sopenharmony_ci  return Operand(
2401cb0ef41Sopenharmony_ci      kRootRegister,
2411cb0ef41Sopenharmony_ci      RootRegisterOffsetForExternalReferenceTableEntry(isolate(), reference));
2421cb0ef41Sopenharmony_ci}
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci// TODO(v8:6666): If possible, refactor into a platform-independent function in
2451cb0ef41Sopenharmony_ci// TurboAssembler.
2461cb0ef41Sopenharmony_ciOperand TurboAssembler::HeapObjectAsOperand(Handle<HeapObject> object) {
2471cb0ef41Sopenharmony_ci  DCHECK(root_array_available());
2481cb0ef41Sopenharmony_ci
2491cb0ef41Sopenharmony_ci  Builtin builtin;
2501cb0ef41Sopenharmony_ci  RootIndex root_index;
2511cb0ef41Sopenharmony_ci  if (isolate()->roots_table().IsRootHandle(object, &root_index)) {
2521cb0ef41Sopenharmony_ci    return RootAsOperand(root_index);
2531cb0ef41Sopenharmony_ci  } else if (isolate()->builtins()->IsBuiltinHandle(object, &builtin)) {
2541cb0ef41Sopenharmony_ci    return Operand(kRootRegister, RootRegisterOffsetForBuiltin(builtin));
2551cb0ef41Sopenharmony_ci  } else if (object.is_identical_to(code_object_) &&
2561cb0ef41Sopenharmony_ci             Builtins::IsBuiltinId(maybe_builtin_)) {
2571cb0ef41Sopenharmony_ci    return Operand(kRootRegister, RootRegisterOffsetForBuiltin(maybe_builtin_));
2581cb0ef41Sopenharmony_ci  } else {
2591cb0ef41Sopenharmony_ci    // Objects in the constants table need an additional indirection, which
2601cb0ef41Sopenharmony_ci    // cannot be represented as a single Operand.
2611cb0ef41Sopenharmony_ci    UNREACHABLE();
2621cb0ef41Sopenharmony_ci  }
2631cb0ef41Sopenharmony_ci}
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_civoid TurboAssembler::LoadFromConstantsTable(Register destination,
2661cb0ef41Sopenharmony_ci                                            int constant_index) {
2671cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
2681cb0ef41Sopenharmony_ci  DCHECK(RootsTable::IsImmortalImmovable(RootIndex::kBuiltinsConstantsTable));
2691cb0ef41Sopenharmony_ci  LoadRoot(destination, RootIndex::kBuiltinsConstantsTable);
2701cb0ef41Sopenharmony_ci  mov(destination,
2711cb0ef41Sopenharmony_ci      FieldOperand(destination, FixedArray::OffsetOfElementAt(constant_index)));
2721cb0ef41Sopenharmony_ci}
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_civoid TurboAssembler::LoadRootRegisterOffset(Register destination,
2751cb0ef41Sopenharmony_ci                                            intptr_t offset) {
2761cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
2771cb0ef41Sopenharmony_ci  DCHECK(is_int32(offset));
2781cb0ef41Sopenharmony_ci  DCHECK(root_array_available());
2791cb0ef41Sopenharmony_ci  if (offset == 0) {
2801cb0ef41Sopenharmony_ci    mov(destination, kRootRegister);
2811cb0ef41Sopenharmony_ci  } else {
2821cb0ef41Sopenharmony_ci    lea(destination, Operand(kRootRegister, static_cast<int32_t>(offset)));
2831cb0ef41Sopenharmony_ci  }
2841cb0ef41Sopenharmony_ci}
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_civoid TurboAssembler::LoadRootRelative(Register destination, int32_t offset) {
2871cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
2881cb0ef41Sopenharmony_ci  DCHECK(root_array_available());
2891cb0ef41Sopenharmony_ci  mov(destination, Operand(kRootRegister, offset));
2901cb0ef41Sopenharmony_ci}
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_civoid TurboAssembler::LoadAddress(Register destination,
2931cb0ef41Sopenharmony_ci                                 ExternalReference source) {
2941cb0ef41Sopenharmony_ci  // TODO(jgruber): Add support for enable_root_relative_access.
2951cb0ef41Sopenharmony_ci  if (root_array_available() && options().isolate_independent_code) {
2961cb0ef41Sopenharmony_ci    IndirectLoadExternalReference(destination, source);
2971cb0ef41Sopenharmony_ci    return;
2981cb0ef41Sopenharmony_ci  }
2991cb0ef41Sopenharmony_ci  mov(destination, Immediate(source));
3001cb0ef41Sopenharmony_ci}
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_cistatic constexpr Register saved_regs[] = {eax, ecx, edx};
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_cistatic constexpr int kNumberOfSavedRegs = sizeof(saved_regs) / sizeof(Register);
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ciint TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
3071cb0ef41Sopenharmony_ci                                                    Register exclusion1,
3081cb0ef41Sopenharmony_ci                                                    Register exclusion2,
3091cb0ef41Sopenharmony_ci                                                    Register exclusion3) const {
3101cb0ef41Sopenharmony_ci  int bytes = 0;
3111cb0ef41Sopenharmony_ci  for (int i = 0; i < kNumberOfSavedRegs; i++) {
3121cb0ef41Sopenharmony_ci    Register reg = saved_regs[i];
3131cb0ef41Sopenharmony_ci    if (reg != exclusion1 && reg != exclusion2 && reg != exclusion3) {
3141cb0ef41Sopenharmony_ci      bytes += kSystemPointerSize;
3151cb0ef41Sopenharmony_ci    }
3161cb0ef41Sopenharmony_ci  }
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci  if (fp_mode == SaveFPRegsMode::kSave) {
3191cb0ef41Sopenharmony_ci    // Count all XMM registers except XMM0.
3201cb0ef41Sopenharmony_ci    bytes += kStackSavedSavedFPSize * (XMMRegister::kNumRegisters - 1);
3211cb0ef41Sopenharmony_ci  }
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci  return bytes;
3241cb0ef41Sopenharmony_ci}
3251cb0ef41Sopenharmony_ci
3261cb0ef41Sopenharmony_ciint TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
3271cb0ef41Sopenharmony_ci                                    Register exclusion2, Register exclusion3) {
3281cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
3291cb0ef41Sopenharmony_ci  // We don't allow a GC in a write barrier slow path so there is no need to
3301cb0ef41Sopenharmony_ci  // store the registers in any particular way, but we do have to store and
3311cb0ef41Sopenharmony_ci  // restore them.
3321cb0ef41Sopenharmony_ci  int bytes = 0;
3331cb0ef41Sopenharmony_ci  for (int i = 0; i < kNumberOfSavedRegs; i++) {
3341cb0ef41Sopenharmony_ci    Register reg = saved_regs[i];
3351cb0ef41Sopenharmony_ci    if (reg != exclusion1 && reg != exclusion2 && reg != exclusion3) {
3361cb0ef41Sopenharmony_ci      push(reg);
3371cb0ef41Sopenharmony_ci      bytes += kSystemPointerSize;
3381cb0ef41Sopenharmony_ci    }
3391cb0ef41Sopenharmony_ci  }
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  if (fp_mode == SaveFPRegsMode::kSave) {
3421cb0ef41Sopenharmony_ci    // Save all XMM registers except XMM0.
3431cb0ef41Sopenharmony_ci    const int delta = kStackSavedSavedFPSize * (XMMRegister::kNumRegisters - 1);
3441cb0ef41Sopenharmony_ci    AllocateStackSpace(delta);
3451cb0ef41Sopenharmony_ci    for (int i = XMMRegister::kNumRegisters - 1; i > 0; i--) {
3461cb0ef41Sopenharmony_ci      XMMRegister reg = XMMRegister::from_code(i);
3471cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
3481cb0ef41Sopenharmony_ci      Movdqu(Operand(esp, (i - 1) * kStackSavedSavedFPSize), reg);
3491cb0ef41Sopenharmony_ci#else
3501cb0ef41Sopenharmony_ci      Movsd(Operand(esp, (i - 1) * kStackSavedSavedFPSize), reg);
3511cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
3521cb0ef41Sopenharmony_ci    }
3531cb0ef41Sopenharmony_ci    bytes += delta;
3541cb0ef41Sopenharmony_ci  }
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci  return bytes;
3571cb0ef41Sopenharmony_ci}
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ciint TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
3601cb0ef41Sopenharmony_ci                                   Register exclusion2, Register exclusion3) {
3611cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
3621cb0ef41Sopenharmony_ci  int bytes = 0;
3631cb0ef41Sopenharmony_ci  if (fp_mode == SaveFPRegsMode::kSave) {
3641cb0ef41Sopenharmony_ci    // Restore all XMM registers except XMM0.
3651cb0ef41Sopenharmony_ci    const int delta = kStackSavedSavedFPSize * (XMMRegister::kNumRegisters - 1);
3661cb0ef41Sopenharmony_ci    for (int i = XMMRegister::kNumRegisters - 1; i > 0; i--) {
3671cb0ef41Sopenharmony_ci      XMMRegister reg = XMMRegister::from_code(i);
3681cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
3691cb0ef41Sopenharmony_ci      Movdqu(reg, Operand(esp, (i - 1) * kStackSavedSavedFPSize));
3701cb0ef41Sopenharmony_ci#else
3711cb0ef41Sopenharmony_ci      Movsd(reg, Operand(esp, (i - 1) * kStackSavedSavedFPSize));
3721cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
3731cb0ef41Sopenharmony_ci    }
3741cb0ef41Sopenharmony_ci    add(esp, Immediate(delta));
3751cb0ef41Sopenharmony_ci    bytes += delta;
3761cb0ef41Sopenharmony_ci  }
3771cb0ef41Sopenharmony_ci
3781cb0ef41Sopenharmony_ci  for (int i = kNumberOfSavedRegs - 1; i >= 0; i--) {
3791cb0ef41Sopenharmony_ci    Register reg = saved_regs[i];
3801cb0ef41Sopenharmony_ci    if (reg != exclusion1 && reg != exclusion2 && reg != exclusion3) {
3811cb0ef41Sopenharmony_ci      pop(reg);
3821cb0ef41Sopenharmony_ci      bytes += kSystemPointerSize;
3831cb0ef41Sopenharmony_ci    }
3841cb0ef41Sopenharmony_ci  }
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci  return bytes;
3871cb0ef41Sopenharmony_ci}
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_civoid MacroAssembler::RecordWriteField(Register object, int offset,
3901cb0ef41Sopenharmony_ci                                      Register value, Register slot_address,
3911cb0ef41Sopenharmony_ci                                      SaveFPRegsMode save_fp,
3921cb0ef41Sopenharmony_ci                                      RememberedSetAction remembered_set_action,
3931cb0ef41Sopenharmony_ci                                      SmiCheck smi_check) {
3941cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
3951cb0ef41Sopenharmony_ci  // First, check if a write barrier is even needed. The tests below
3961cb0ef41Sopenharmony_ci  // catch stores of Smis.
3971cb0ef41Sopenharmony_ci  Label done;
3981cb0ef41Sopenharmony_ci
3991cb0ef41Sopenharmony_ci  // Skip barrier if writing a smi.
4001cb0ef41Sopenharmony_ci  if (smi_check == SmiCheck::kInline) {
4011cb0ef41Sopenharmony_ci    JumpIfSmi(value, &done);
4021cb0ef41Sopenharmony_ci  }
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_ci  // Although the object register is tagged, the offset is relative to the start
4051cb0ef41Sopenharmony_ci  // of the object, so so offset must be a multiple of kTaggedSize.
4061cb0ef41Sopenharmony_ci  DCHECK(IsAligned(offset, kTaggedSize));
4071cb0ef41Sopenharmony_ci
4081cb0ef41Sopenharmony_ci  lea(slot_address, FieldOperand(object, offset));
4091cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
4101cb0ef41Sopenharmony_ci    Label ok;
4111cb0ef41Sopenharmony_ci    test_b(slot_address, Immediate(kTaggedSize - 1));
4121cb0ef41Sopenharmony_ci    j(zero, &ok, Label::kNear);
4131cb0ef41Sopenharmony_ci    int3();
4141cb0ef41Sopenharmony_ci    bind(&ok);
4151cb0ef41Sopenharmony_ci  }
4161cb0ef41Sopenharmony_ci
4171cb0ef41Sopenharmony_ci  RecordWrite(object, slot_address, value, save_fp, remembered_set_action,
4181cb0ef41Sopenharmony_ci              SmiCheck::kOmit);
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_ci  bind(&done);
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_ci  // Clobber clobbered input registers when running with the debug-code flag
4231cb0ef41Sopenharmony_ci  // turned on to provoke errors.
4241cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
4251cb0ef41Sopenharmony_ci    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
4261cb0ef41Sopenharmony_ci    mov(slot_address, Immediate(bit_cast<int32_t>(kZapValue)));
4271cb0ef41Sopenharmony_ci  }
4281cb0ef41Sopenharmony_ci}
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_civoid TurboAssembler::MaybeSaveRegisters(RegList registers) {
4311cb0ef41Sopenharmony_ci  for (Register reg : registers) {
4321cb0ef41Sopenharmony_ci    push(reg);
4331cb0ef41Sopenharmony_ci  }
4341cb0ef41Sopenharmony_ci}
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_civoid TurboAssembler::MaybeRestoreRegisters(RegList registers) {
4371cb0ef41Sopenharmony_ci  for (Register reg : base::Reversed(registers)) {
4381cb0ef41Sopenharmony_ci    pop(reg);
4391cb0ef41Sopenharmony_ci  }
4401cb0ef41Sopenharmony_ci}
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_civoid TurboAssembler::CallEphemeronKeyBarrier(Register object,
4431cb0ef41Sopenharmony_ci                                             Register slot_address,
4441cb0ef41Sopenharmony_ci                                             SaveFPRegsMode fp_mode) {
4451cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
4461cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(object, slot_address));
4471cb0ef41Sopenharmony_ci  RegList registers =
4481cb0ef41Sopenharmony_ci      WriteBarrierDescriptor::ComputeSavedRegisters(object, slot_address);
4491cb0ef41Sopenharmony_ci  MaybeSaveRegisters(registers);
4501cb0ef41Sopenharmony_ci
4511cb0ef41Sopenharmony_ci  Register object_parameter = WriteBarrierDescriptor::ObjectRegister();
4521cb0ef41Sopenharmony_ci  Register slot_address_parameter =
4531cb0ef41Sopenharmony_ci      WriteBarrierDescriptor::SlotAddressRegister();
4541cb0ef41Sopenharmony_ci
4551cb0ef41Sopenharmony_ci  push(object);
4561cb0ef41Sopenharmony_ci  push(slot_address);
4571cb0ef41Sopenharmony_ci  pop(slot_address_parameter);
4581cb0ef41Sopenharmony_ci  pop(object_parameter);
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_ci  Call(isolate()->builtins()->code_handle(
4611cb0ef41Sopenharmony_ci           Builtins::GetEphemeronKeyBarrierStub(fp_mode)),
4621cb0ef41Sopenharmony_ci       RelocInfo::CODE_TARGET);
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ci  MaybeRestoreRegisters(registers);
4651cb0ef41Sopenharmony_ci}
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_civoid TurboAssembler::CallRecordWriteStubSaveRegisters(
4681cb0ef41Sopenharmony_ci    Register object, Register slot_address,
4691cb0ef41Sopenharmony_ci    RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
4701cb0ef41Sopenharmony_ci    StubCallMode mode) {
4711cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
4721cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(object, slot_address));
4731cb0ef41Sopenharmony_ci  RegList registers =
4741cb0ef41Sopenharmony_ci      WriteBarrierDescriptor::ComputeSavedRegisters(object, slot_address);
4751cb0ef41Sopenharmony_ci  MaybeSaveRegisters(registers);
4761cb0ef41Sopenharmony_ci
4771cb0ef41Sopenharmony_ci  Register object_parameter = WriteBarrierDescriptor::ObjectRegister();
4781cb0ef41Sopenharmony_ci  Register slot_address_parameter =
4791cb0ef41Sopenharmony_ci      WriteBarrierDescriptor::SlotAddressRegister();
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_ci  push(object);
4821cb0ef41Sopenharmony_ci  push(slot_address);
4831cb0ef41Sopenharmony_ci  pop(slot_address_parameter);
4841cb0ef41Sopenharmony_ci  pop(object_parameter);
4851cb0ef41Sopenharmony_ci
4861cb0ef41Sopenharmony_ci  CallRecordWriteStub(object_parameter, slot_address_parameter,
4871cb0ef41Sopenharmony_ci                      remembered_set_action, fp_mode, mode);
4881cb0ef41Sopenharmony_ci
4891cb0ef41Sopenharmony_ci  MaybeRestoreRegisters(registers);
4901cb0ef41Sopenharmony_ci}
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_civoid TurboAssembler::CallRecordWriteStub(
4931cb0ef41Sopenharmony_ci    Register object, Register slot_address,
4941cb0ef41Sopenharmony_ci    RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode,
4951cb0ef41Sopenharmony_ci    StubCallMode mode) {
4961cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
4971cb0ef41Sopenharmony_ci  // Use CallRecordWriteStubSaveRegisters if the object and slot registers
4981cb0ef41Sopenharmony_ci  // need to be caller saved.
4991cb0ef41Sopenharmony_ci  DCHECK_EQ(WriteBarrierDescriptor::ObjectRegister(), object);
5001cb0ef41Sopenharmony_ci  DCHECK_EQ(WriteBarrierDescriptor::SlotAddressRegister(), slot_address);
5011cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
5021cb0ef41Sopenharmony_ci  if (mode == StubCallMode::kCallWasmRuntimeStub) {
5031cb0ef41Sopenharmony_ci    // Use {wasm_call} for direct Wasm call within a module.
5041cb0ef41Sopenharmony_ci    auto wasm_target =
5051cb0ef41Sopenharmony_ci        wasm::WasmCode::GetRecordWriteStub(remembered_set_action, fp_mode);
5061cb0ef41Sopenharmony_ci    wasm_call(wasm_target, RelocInfo::WASM_STUB_CALL);
5071cb0ef41Sopenharmony_ci#else
5081cb0ef41Sopenharmony_ci  if (false) {
5091cb0ef41Sopenharmony_ci#endif
5101cb0ef41Sopenharmony_ci  } else {
5111cb0ef41Sopenharmony_ci    Builtin builtin =
5121cb0ef41Sopenharmony_ci        Builtins::GetRecordWriteStub(remembered_set_action, fp_mode);
5131cb0ef41Sopenharmony_ci    if (options().inline_offheap_trampolines) {
5141cb0ef41Sopenharmony_ci      CallBuiltin(builtin);
5151cb0ef41Sopenharmony_ci    } else {
5161cb0ef41Sopenharmony_ci      Handle<Code> code_target = isolate()->builtins()->code_handle(builtin);
5171cb0ef41Sopenharmony_ci      Call(code_target, RelocInfo::CODE_TARGET);
5181cb0ef41Sopenharmony_ci    }
5191cb0ef41Sopenharmony_ci  }
5201cb0ef41Sopenharmony_ci}
5211cb0ef41Sopenharmony_ci
5221cb0ef41Sopenharmony_civoid MacroAssembler::RecordWrite(Register object, Register slot_address,
5231cb0ef41Sopenharmony_ci                                 Register value, SaveFPRegsMode fp_mode,
5241cb0ef41Sopenharmony_ci                                 RememberedSetAction remembered_set_action,
5251cb0ef41Sopenharmony_ci                                 SmiCheck smi_check) {
5261cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
5271cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(object, value, slot_address));
5281cb0ef41Sopenharmony_ci  AssertNotSmi(object);
5291cb0ef41Sopenharmony_ci
5301cb0ef41Sopenharmony_ci  if ((remembered_set_action == RememberedSetAction::kOmit &&
5311cb0ef41Sopenharmony_ci       !FLAG_incremental_marking) ||
5321cb0ef41Sopenharmony_ci      FLAG_disable_write_barriers) {
5331cb0ef41Sopenharmony_ci    return;
5341cb0ef41Sopenharmony_ci  }
5351cb0ef41Sopenharmony_ci
5361cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
5371cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT_STRING(this, "Verify slot_address");
5381cb0ef41Sopenharmony_ci    Label ok;
5391cb0ef41Sopenharmony_ci    cmp(value, Operand(slot_address, 0));
5401cb0ef41Sopenharmony_ci    j(equal, &ok, Label::kNear);
5411cb0ef41Sopenharmony_ci    int3();
5421cb0ef41Sopenharmony_ci    bind(&ok);
5431cb0ef41Sopenharmony_ci  }
5441cb0ef41Sopenharmony_ci
5451cb0ef41Sopenharmony_ci  // First, check if a write barrier is even needed. The tests below
5461cb0ef41Sopenharmony_ci  // catch stores of Smis and stores into young gen.
5471cb0ef41Sopenharmony_ci  Label done;
5481cb0ef41Sopenharmony_ci
5491cb0ef41Sopenharmony_ci  if (smi_check == SmiCheck::kInline) {
5501cb0ef41Sopenharmony_ci    // Skip barrier if writing a smi.
5511cb0ef41Sopenharmony_ci    JumpIfSmi(value, &done, Label::kNear);
5521cb0ef41Sopenharmony_ci  }
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci  CheckPageFlag(value,
5551cb0ef41Sopenharmony_ci                value,  // Used as scratch.
5561cb0ef41Sopenharmony_ci                MemoryChunk::kPointersToHereAreInterestingMask, zero, &done,
5571cb0ef41Sopenharmony_ci                Label::kNear);
5581cb0ef41Sopenharmony_ci  CheckPageFlag(object,
5591cb0ef41Sopenharmony_ci                value,  // Used as scratch.
5601cb0ef41Sopenharmony_ci                MemoryChunk::kPointersFromHereAreInterestingMask, zero, &done,
5611cb0ef41Sopenharmony_ci                Label::kNear);
5621cb0ef41Sopenharmony_ci  RecordComment("CheckPageFlag]");
5631cb0ef41Sopenharmony_ci
5641cb0ef41Sopenharmony_ci  CallRecordWriteStub(object, slot_address, remembered_set_action, fp_mode);
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_ci  bind(&done);
5671cb0ef41Sopenharmony_ci
5681cb0ef41Sopenharmony_ci  // Clobber clobbered registers when running with the debug-code flag
5691cb0ef41Sopenharmony_ci  // turned on to provoke errors.
5701cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
5711cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT_STRING(this, "Clobber slot_address and value");
5721cb0ef41Sopenharmony_ci    mov(slot_address, Immediate(bit_cast<int32_t>(kZapValue)));
5731cb0ef41Sopenharmony_ci    mov(value, Immediate(bit_cast<int32_t>(kZapValue)));
5741cb0ef41Sopenharmony_ci  }
5751cb0ef41Sopenharmony_ci}
5761cb0ef41Sopenharmony_ci
5771cb0ef41Sopenharmony_civoid TurboAssembler::Cvtsi2ss(XMMRegister dst, Operand src) {
5781cb0ef41Sopenharmony_ci  xorps(dst, dst);
5791cb0ef41Sopenharmony_ci  cvtsi2ss(dst, src);
5801cb0ef41Sopenharmony_ci}
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_civoid TurboAssembler::Cvtsi2sd(XMMRegister dst, Operand src) {
5831cb0ef41Sopenharmony_ci  xorpd(dst, dst);
5841cb0ef41Sopenharmony_ci  cvtsi2sd(dst, src);
5851cb0ef41Sopenharmony_ci}
5861cb0ef41Sopenharmony_ci
5871cb0ef41Sopenharmony_civoid TurboAssembler::Cvtui2ss(XMMRegister dst, Operand src, Register tmp) {
5881cb0ef41Sopenharmony_ci  Label done;
5891cb0ef41Sopenharmony_ci  Register src_reg = src.is_reg_only() ? src.reg() : tmp;
5901cb0ef41Sopenharmony_ci  if (src_reg == tmp) mov(tmp, src);
5911cb0ef41Sopenharmony_ci  cvtsi2ss(dst, src_reg);
5921cb0ef41Sopenharmony_ci  test(src_reg, src_reg);
5931cb0ef41Sopenharmony_ci  j(positive, &done, Label::kNear);
5941cb0ef41Sopenharmony_ci
5951cb0ef41Sopenharmony_ci  // Compute {src/2 | (src&1)} (retain the LSB to avoid rounding errors).
5961cb0ef41Sopenharmony_ci  if (src_reg != tmp) mov(tmp, src_reg);
5971cb0ef41Sopenharmony_ci  shr(tmp, 1);
5981cb0ef41Sopenharmony_ci  // The LSB is shifted into CF. If it is set, set the LSB in {tmp}.
5991cb0ef41Sopenharmony_ci  Label msb_not_set;
6001cb0ef41Sopenharmony_ci  j(not_carry, &msb_not_set, Label::kNear);
6011cb0ef41Sopenharmony_ci  or_(tmp, Immediate(1));
6021cb0ef41Sopenharmony_ci  bind(&msb_not_set);
6031cb0ef41Sopenharmony_ci  cvtsi2ss(dst, tmp);
6041cb0ef41Sopenharmony_ci  addss(dst, dst);
6051cb0ef41Sopenharmony_ci  bind(&done);
6061cb0ef41Sopenharmony_ci}
6071cb0ef41Sopenharmony_ci
6081cb0ef41Sopenharmony_civoid TurboAssembler::Cvttss2ui(Register dst, Operand src, XMMRegister tmp) {
6091cb0ef41Sopenharmony_ci  Label done;
6101cb0ef41Sopenharmony_ci  cvttss2si(dst, src);
6111cb0ef41Sopenharmony_ci  test(dst, dst);
6121cb0ef41Sopenharmony_ci  j(positive, &done);
6131cb0ef41Sopenharmony_ci  Move(tmp, static_cast<float>(INT32_MIN));
6141cb0ef41Sopenharmony_ci  addss(tmp, src);
6151cb0ef41Sopenharmony_ci  cvttss2si(dst, tmp);
6161cb0ef41Sopenharmony_ci  or_(dst, Immediate(0x80000000));
6171cb0ef41Sopenharmony_ci  bind(&done);
6181cb0ef41Sopenharmony_ci}
6191cb0ef41Sopenharmony_ci
6201cb0ef41Sopenharmony_civoid TurboAssembler::Cvtui2sd(XMMRegister dst, Operand src, Register scratch) {
6211cb0ef41Sopenharmony_ci  Label done;
6221cb0ef41Sopenharmony_ci  cmp(src, Immediate(0));
6231cb0ef41Sopenharmony_ci  ExternalReference uint32_bias = ExternalReference::address_of_uint32_bias();
6241cb0ef41Sopenharmony_ci  Cvtsi2sd(dst, src);
6251cb0ef41Sopenharmony_ci  j(not_sign, &done, Label::kNear);
6261cb0ef41Sopenharmony_ci  addsd(dst, ExternalReferenceAsOperand(uint32_bias, scratch));
6271cb0ef41Sopenharmony_ci  bind(&done);
6281cb0ef41Sopenharmony_ci}
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_civoid TurboAssembler::Cvttsd2ui(Register dst, Operand src, XMMRegister tmp) {
6311cb0ef41Sopenharmony_ci  Move(tmp, -2147483648.0);
6321cb0ef41Sopenharmony_ci  addsd(tmp, src);
6331cb0ef41Sopenharmony_ci  cvttsd2si(dst, tmp);
6341cb0ef41Sopenharmony_ci  add(dst, Immediate(0x80000000));
6351cb0ef41Sopenharmony_ci}
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_civoid TurboAssembler::ShlPair(Register high, Register low, uint8_t shift) {
6381cb0ef41Sopenharmony_ci  DCHECK_GE(63, shift);
6391cb0ef41Sopenharmony_ci  if (shift >= 32) {
6401cb0ef41Sopenharmony_ci    mov(high, low);
6411cb0ef41Sopenharmony_ci    if (shift != 32) shl(high, shift - 32);
6421cb0ef41Sopenharmony_ci    xor_(low, low);
6431cb0ef41Sopenharmony_ci  } else {
6441cb0ef41Sopenharmony_ci    shld(high, low, shift);
6451cb0ef41Sopenharmony_ci    shl(low, shift);
6461cb0ef41Sopenharmony_ci  }
6471cb0ef41Sopenharmony_ci}
6481cb0ef41Sopenharmony_ci
6491cb0ef41Sopenharmony_civoid TurboAssembler::ShlPair_cl(Register high, Register low) {
6501cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
6511cb0ef41Sopenharmony_ci  shld_cl(high, low);
6521cb0ef41Sopenharmony_ci  shl_cl(low);
6531cb0ef41Sopenharmony_ci  Label done;
6541cb0ef41Sopenharmony_ci  test(ecx, Immediate(0x20));
6551cb0ef41Sopenharmony_ci  j(equal, &done, Label::kNear);
6561cb0ef41Sopenharmony_ci  mov(high, low);
6571cb0ef41Sopenharmony_ci  xor_(low, low);
6581cb0ef41Sopenharmony_ci  bind(&done);
6591cb0ef41Sopenharmony_ci}
6601cb0ef41Sopenharmony_ci
6611cb0ef41Sopenharmony_civoid TurboAssembler::ShrPair(Register high, Register low, uint8_t shift) {
6621cb0ef41Sopenharmony_ci  DCHECK_GE(63, shift);
6631cb0ef41Sopenharmony_ci  if (shift >= 32) {
6641cb0ef41Sopenharmony_ci    mov(low, high);
6651cb0ef41Sopenharmony_ci    if (shift != 32) shr(low, shift - 32);
6661cb0ef41Sopenharmony_ci    xor_(high, high);
6671cb0ef41Sopenharmony_ci  } else {
6681cb0ef41Sopenharmony_ci    shrd(low, high, shift);
6691cb0ef41Sopenharmony_ci    shr(high, shift);
6701cb0ef41Sopenharmony_ci  }
6711cb0ef41Sopenharmony_ci}
6721cb0ef41Sopenharmony_ci
6731cb0ef41Sopenharmony_civoid TurboAssembler::ShrPair_cl(Register high, Register low) {
6741cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
6751cb0ef41Sopenharmony_ci  shrd_cl(low, high);
6761cb0ef41Sopenharmony_ci  shr_cl(high);
6771cb0ef41Sopenharmony_ci  Label done;
6781cb0ef41Sopenharmony_ci  test(ecx, Immediate(0x20));
6791cb0ef41Sopenharmony_ci  j(equal, &done, Label::kNear);
6801cb0ef41Sopenharmony_ci  mov(low, high);
6811cb0ef41Sopenharmony_ci  xor_(high, high);
6821cb0ef41Sopenharmony_ci  bind(&done);
6831cb0ef41Sopenharmony_ci}
6841cb0ef41Sopenharmony_ci
6851cb0ef41Sopenharmony_civoid TurboAssembler::SarPair(Register high, Register low, uint8_t shift) {
6861cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
6871cb0ef41Sopenharmony_ci  DCHECK_GE(63, shift);
6881cb0ef41Sopenharmony_ci  if (shift >= 32) {
6891cb0ef41Sopenharmony_ci    mov(low, high);
6901cb0ef41Sopenharmony_ci    if (shift != 32) sar(low, shift - 32);
6911cb0ef41Sopenharmony_ci    sar(high, 31);
6921cb0ef41Sopenharmony_ci  } else {
6931cb0ef41Sopenharmony_ci    shrd(low, high, shift);
6941cb0ef41Sopenharmony_ci    sar(high, shift);
6951cb0ef41Sopenharmony_ci  }
6961cb0ef41Sopenharmony_ci}
6971cb0ef41Sopenharmony_ci
6981cb0ef41Sopenharmony_civoid TurboAssembler::SarPair_cl(Register high, Register low) {
6991cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
7001cb0ef41Sopenharmony_ci  shrd_cl(low, high);
7011cb0ef41Sopenharmony_ci  sar_cl(high);
7021cb0ef41Sopenharmony_ci  Label done;
7031cb0ef41Sopenharmony_ci  test(ecx, Immediate(0x20));
7041cb0ef41Sopenharmony_ci  j(equal, &done, Label::kNear);
7051cb0ef41Sopenharmony_ci  mov(low, high);
7061cb0ef41Sopenharmony_ci  sar(high, 31);
7071cb0ef41Sopenharmony_ci  bind(&done);
7081cb0ef41Sopenharmony_ci}
7091cb0ef41Sopenharmony_ci
7101cb0ef41Sopenharmony_civoid TurboAssembler::LoadMap(Register destination, Register object) {
7111cb0ef41Sopenharmony_ci  mov(destination, FieldOperand(object, HeapObject::kMapOffset));
7121cb0ef41Sopenharmony_ci}
7131cb0ef41Sopenharmony_ci
7141cb0ef41Sopenharmony_civoid MacroAssembler::CmpObjectType(Register heap_object, InstanceType type,
7151cb0ef41Sopenharmony_ci                                   Register map) {
7161cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
7171cb0ef41Sopenharmony_ci  LoadMap(map, heap_object);
7181cb0ef41Sopenharmony_ci  CmpInstanceType(map, type);
7191cb0ef41Sopenharmony_ci}
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_civoid MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
7221cb0ef41Sopenharmony_ci  cmpw(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
7231cb0ef41Sopenharmony_ci}
7241cb0ef41Sopenharmony_ci
7251cb0ef41Sopenharmony_civoid MacroAssembler::CmpInstanceTypeRange(Register map,
7261cb0ef41Sopenharmony_ci                                          Register instance_type_out,
7271cb0ef41Sopenharmony_ci                                          Register scratch,
7281cb0ef41Sopenharmony_ci                                          InstanceType lower_limit,
7291cb0ef41Sopenharmony_ci                                          InstanceType higher_limit) {
7301cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
7311cb0ef41Sopenharmony_ci  DCHECK_LT(lower_limit, higher_limit);
7321cb0ef41Sopenharmony_ci  movzx_w(instance_type_out, FieldOperand(map, Map::kInstanceTypeOffset));
7331cb0ef41Sopenharmony_ci  CompareRange(instance_type_out, lower_limit, higher_limit, scratch);
7341cb0ef41Sopenharmony_ci}
7351cb0ef41Sopenharmony_ci
7361cb0ef41Sopenharmony_civoid MacroAssembler::AssertSmi(Register object) {
7371cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
7381cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT(this);
7391cb0ef41Sopenharmony_ci    test(object, Immediate(kSmiTagMask));
7401cb0ef41Sopenharmony_ci    Check(equal, AbortReason::kOperandIsNotASmi);
7411cb0ef41Sopenharmony_ci  }
7421cb0ef41Sopenharmony_ci}
7431cb0ef41Sopenharmony_ci
7441cb0ef41Sopenharmony_civoid MacroAssembler::AssertConstructor(Register object) {
7451cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
7461cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT(this);
7471cb0ef41Sopenharmony_ci    test(object, Immediate(kSmiTagMask));
7481cb0ef41Sopenharmony_ci    Check(not_equal, AbortReason::kOperandIsASmiAndNotAConstructor);
7491cb0ef41Sopenharmony_ci    Push(object);
7501cb0ef41Sopenharmony_ci    LoadMap(object, object);
7511cb0ef41Sopenharmony_ci    test_b(FieldOperand(object, Map::kBitFieldOffset),
7521cb0ef41Sopenharmony_ci           Immediate(Map::Bits1::IsConstructorBit::kMask));
7531cb0ef41Sopenharmony_ci    Pop(object);
7541cb0ef41Sopenharmony_ci    Check(not_zero, AbortReason::kOperandIsNotAConstructor);
7551cb0ef41Sopenharmony_ci  }
7561cb0ef41Sopenharmony_ci}
7571cb0ef41Sopenharmony_ci
7581cb0ef41Sopenharmony_civoid MacroAssembler::AssertFunction(Register object, Register scratch) {
7591cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
7601cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT(this);
7611cb0ef41Sopenharmony_ci    test(object, Immediate(kSmiTagMask));
7621cb0ef41Sopenharmony_ci    Check(not_equal, AbortReason::kOperandIsASmiAndNotAFunction);
7631cb0ef41Sopenharmony_ci    Push(object);
7641cb0ef41Sopenharmony_ci    LoadMap(object, object);
7651cb0ef41Sopenharmony_ci    CmpInstanceTypeRange(object, scratch, scratch, FIRST_JS_FUNCTION_TYPE,
7661cb0ef41Sopenharmony_ci                         LAST_JS_FUNCTION_TYPE);
7671cb0ef41Sopenharmony_ci    Pop(object);
7681cb0ef41Sopenharmony_ci    Check(below_equal, AbortReason::kOperandIsNotAFunction);
7691cb0ef41Sopenharmony_ci  }
7701cb0ef41Sopenharmony_ci}
7711cb0ef41Sopenharmony_ci
7721cb0ef41Sopenharmony_civoid MacroAssembler::AssertCallableFunction(Register object, Register scratch) {
7731cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
7741cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT(this);
7751cb0ef41Sopenharmony_ci    test(object, Immediate(kSmiTagMask));
7761cb0ef41Sopenharmony_ci    Check(not_equal, AbortReason::kOperandIsASmiAndNotAFunction);
7771cb0ef41Sopenharmony_ci    Push(object);
7781cb0ef41Sopenharmony_ci    LoadMap(object, object);
7791cb0ef41Sopenharmony_ci    CmpInstanceTypeRange(object, scratch, scratch,
7801cb0ef41Sopenharmony_ci                         FIRST_CALLABLE_JS_FUNCTION_TYPE,
7811cb0ef41Sopenharmony_ci                         LAST_CALLABLE_JS_FUNCTION_TYPE);
7821cb0ef41Sopenharmony_ci    Pop(object);
7831cb0ef41Sopenharmony_ci    Check(below_equal, AbortReason::kOperandIsNotACallableFunction);
7841cb0ef41Sopenharmony_ci  }
7851cb0ef41Sopenharmony_ci}
7861cb0ef41Sopenharmony_ci
7871cb0ef41Sopenharmony_civoid MacroAssembler::AssertBoundFunction(Register object) {
7881cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
7891cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT(this);
7901cb0ef41Sopenharmony_ci    test(object, Immediate(kSmiTagMask));
7911cb0ef41Sopenharmony_ci    Check(not_equal, AbortReason::kOperandIsASmiAndNotABoundFunction);
7921cb0ef41Sopenharmony_ci    Push(object);
7931cb0ef41Sopenharmony_ci    CmpObjectType(object, JS_BOUND_FUNCTION_TYPE, object);
7941cb0ef41Sopenharmony_ci    Pop(object);
7951cb0ef41Sopenharmony_ci    Check(equal, AbortReason::kOperandIsNotABoundFunction);
7961cb0ef41Sopenharmony_ci  }
7971cb0ef41Sopenharmony_ci}
7981cb0ef41Sopenharmony_ci
7991cb0ef41Sopenharmony_civoid MacroAssembler::AssertGeneratorObject(Register object) {
8001cb0ef41Sopenharmony_ci  if (!FLAG_debug_code) return;
8011cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
8021cb0ef41Sopenharmony_ci
8031cb0ef41Sopenharmony_ci  test(object, Immediate(kSmiTagMask));
8041cb0ef41Sopenharmony_ci  Check(not_equal, AbortReason::kOperandIsASmiAndNotAGeneratorObject);
8051cb0ef41Sopenharmony_ci
8061cb0ef41Sopenharmony_ci  {
8071cb0ef41Sopenharmony_ci    Push(object);
8081cb0ef41Sopenharmony_ci    Register map = object;
8091cb0ef41Sopenharmony_ci
8101cb0ef41Sopenharmony_ci    LoadMap(map, object);
8111cb0ef41Sopenharmony_ci
8121cb0ef41Sopenharmony_ci    Label do_check;
8131cb0ef41Sopenharmony_ci    // Check if JSGeneratorObject
8141cb0ef41Sopenharmony_ci    CmpInstanceType(map, JS_GENERATOR_OBJECT_TYPE);
8151cb0ef41Sopenharmony_ci    j(equal, &do_check, Label::kNear);
8161cb0ef41Sopenharmony_ci
8171cb0ef41Sopenharmony_ci    // Check if JSAsyncFunctionObject.
8181cb0ef41Sopenharmony_ci    CmpInstanceType(map, JS_ASYNC_FUNCTION_OBJECT_TYPE);
8191cb0ef41Sopenharmony_ci    j(equal, &do_check, Label::kNear);
8201cb0ef41Sopenharmony_ci
8211cb0ef41Sopenharmony_ci    // Check if JSAsyncGeneratorObject
8221cb0ef41Sopenharmony_ci    CmpInstanceType(map, JS_ASYNC_GENERATOR_OBJECT_TYPE);
8231cb0ef41Sopenharmony_ci
8241cb0ef41Sopenharmony_ci    bind(&do_check);
8251cb0ef41Sopenharmony_ci    Pop(object);
8261cb0ef41Sopenharmony_ci  }
8271cb0ef41Sopenharmony_ci
8281cb0ef41Sopenharmony_ci  Check(equal, AbortReason::kOperandIsNotAGeneratorObject);
8291cb0ef41Sopenharmony_ci}
8301cb0ef41Sopenharmony_ci
8311cb0ef41Sopenharmony_civoid MacroAssembler::AssertUndefinedOrAllocationSite(Register object,
8321cb0ef41Sopenharmony_ci                                                     Register scratch) {
8331cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
8341cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT(this);
8351cb0ef41Sopenharmony_ci    Label done_checking;
8361cb0ef41Sopenharmony_ci    AssertNotSmi(object);
8371cb0ef41Sopenharmony_ci    CompareRoot(object, scratch, RootIndex::kUndefinedValue);
8381cb0ef41Sopenharmony_ci    j(equal, &done_checking);
8391cb0ef41Sopenharmony_ci    LoadRoot(scratch, RootIndex::kAllocationSiteWithWeakNextMap);
8401cb0ef41Sopenharmony_ci    cmp(FieldOperand(object, 0), scratch);
8411cb0ef41Sopenharmony_ci    Assert(equal, AbortReason::kExpectedUndefinedOrCell);
8421cb0ef41Sopenharmony_ci    bind(&done_checking);
8431cb0ef41Sopenharmony_ci  }
8441cb0ef41Sopenharmony_ci}
8451cb0ef41Sopenharmony_ci
8461cb0ef41Sopenharmony_civoid MacroAssembler::AssertNotSmi(Register object) {
8471cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
8481cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT(this);
8491cb0ef41Sopenharmony_ci    test(object, Immediate(kSmiTagMask));
8501cb0ef41Sopenharmony_ci    Check(not_equal, AbortReason::kOperandIsASmi);
8511cb0ef41Sopenharmony_ci  }
8521cb0ef41Sopenharmony_ci}
8531cb0ef41Sopenharmony_ci
8541cb0ef41Sopenharmony_civoid TurboAssembler::StubPrologue(StackFrame::Type type) {
8551cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
8561cb0ef41Sopenharmony_ci  push(ebp);  // Caller's frame pointer.
8571cb0ef41Sopenharmony_ci  mov(ebp, esp);
8581cb0ef41Sopenharmony_ci  push(Immediate(StackFrame::TypeToMarker(type)));
8591cb0ef41Sopenharmony_ci}
8601cb0ef41Sopenharmony_ci
8611cb0ef41Sopenharmony_civoid TurboAssembler::Prologue() {
8621cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
8631cb0ef41Sopenharmony_ci  push(ebp);  // Caller's frame pointer.
8641cb0ef41Sopenharmony_ci  mov(ebp, esp);
8651cb0ef41Sopenharmony_ci  push(kContextRegister);                 // Callee's context.
8661cb0ef41Sopenharmony_ci  push(kJSFunctionRegister);              // Callee's JS function.
8671cb0ef41Sopenharmony_ci  push(kJavaScriptCallArgCountRegister);  // Actual argument count.
8681cb0ef41Sopenharmony_ci}
8691cb0ef41Sopenharmony_ci
8701cb0ef41Sopenharmony_civoid TurboAssembler::DropArguments(Register count, ArgumentsCountType type,
8711cb0ef41Sopenharmony_ci                                   ArgumentsCountMode mode) {
8721cb0ef41Sopenharmony_ci  int receiver_bytes =
8731cb0ef41Sopenharmony_ci      (mode == kCountExcludesReceiver) ? kSystemPointerSize : 0;
8741cb0ef41Sopenharmony_ci  switch (type) {
8751cb0ef41Sopenharmony_ci    case kCountIsInteger: {
8761cb0ef41Sopenharmony_ci      lea(esp, Operand(esp, count, times_system_pointer_size, receiver_bytes));
8771cb0ef41Sopenharmony_ci      break;
8781cb0ef41Sopenharmony_ci    }
8791cb0ef41Sopenharmony_ci    case kCountIsSmi: {
8801cb0ef41Sopenharmony_ci      STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
8811cb0ef41Sopenharmony_ci      // SMIs are stored shifted left by 1 byte with the tag being 0.
8821cb0ef41Sopenharmony_ci      // This is equivalent to multiplying by 2. To convert SMIs to bytes we
8831cb0ef41Sopenharmony_ci      // can therefore just multiply the stored value by half the system pointer
8841cb0ef41Sopenharmony_ci      // size.
8851cb0ef41Sopenharmony_ci      lea(esp,
8861cb0ef41Sopenharmony_ci          Operand(esp, count, times_half_system_pointer_size, receiver_bytes));
8871cb0ef41Sopenharmony_ci      break;
8881cb0ef41Sopenharmony_ci    }
8891cb0ef41Sopenharmony_ci    case kCountIsBytes: {
8901cb0ef41Sopenharmony_ci      if (receiver_bytes == 0) {
8911cb0ef41Sopenharmony_ci        add(esp, count);
8921cb0ef41Sopenharmony_ci      } else {
8931cb0ef41Sopenharmony_ci        lea(esp, Operand(esp, count, times_1, receiver_bytes));
8941cb0ef41Sopenharmony_ci      }
8951cb0ef41Sopenharmony_ci      break;
8961cb0ef41Sopenharmony_ci    }
8971cb0ef41Sopenharmony_ci  }
8981cb0ef41Sopenharmony_ci}
8991cb0ef41Sopenharmony_ci
9001cb0ef41Sopenharmony_civoid TurboAssembler::DropArguments(Register count, Register scratch,
9011cb0ef41Sopenharmony_ci                                   ArgumentsCountType type,
9021cb0ef41Sopenharmony_ci                                   ArgumentsCountMode mode) {
9031cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(count, scratch));
9041cb0ef41Sopenharmony_ci  PopReturnAddressTo(scratch);
9051cb0ef41Sopenharmony_ci  DropArguments(count, type, mode);
9061cb0ef41Sopenharmony_ci  PushReturnAddressFrom(scratch);
9071cb0ef41Sopenharmony_ci}
9081cb0ef41Sopenharmony_ci
9091cb0ef41Sopenharmony_civoid TurboAssembler::DropArgumentsAndPushNewReceiver(Register argc,
9101cb0ef41Sopenharmony_ci                                                     Register receiver,
9111cb0ef41Sopenharmony_ci                                                     Register scratch,
9121cb0ef41Sopenharmony_ci                                                     ArgumentsCountType type,
9131cb0ef41Sopenharmony_ci                                                     ArgumentsCountMode mode) {
9141cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(argc, receiver, scratch));
9151cb0ef41Sopenharmony_ci  PopReturnAddressTo(scratch);
9161cb0ef41Sopenharmony_ci  DropArguments(argc, type, mode);
9171cb0ef41Sopenharmony_ci  Push(receiver);
9181cb0ef41Sopenharmony_ci  PushReturnAddressFrom(scratch);
9191cb0ef41Sopenharmony_ci}
9201cb0ef41Sopenharmony_ci
9211cb0ef41Sopenharmony_civoid TurboAssembler::DropArgumentsAndPushNewReceiver(Register argc,
9221cb0ef41Sopenharmony_ci                                                     Operand receiver,
9231cb0ef41Sopenharmony_ci                                                     Register scratch,
9241cb0ef41Sopenharmony_ci                                                     ArgumentsCountType type,
9251cb0ef41Sopenharmony_ci                                                     ArgumentsCountMode mode) {
9261cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(argc, scratch));
9271cb0ef41Sopenharmony_ci  DCHECK(!receiver.is_reg(scratch));
9281cb0ef41Sopenharmony_ci  PopReturnAddressTo(scratch);
9291cb0ef41Sopenharmony_ci  DropArguments(argc, type, mode);
9301cb0ef41Sopenharmony_ci  Push(receiver);
9311cb0ef41Sopenharmony_ci  PushReturnAddressFrom(scratch);
9321cb0ef41Sopenharmony_ci}
9331cb0ef41Sopenharmony_ci
9341cb0ef41Sopenharmony_civoid TurboAssembler::EnterFrame(StackFrame::Type type) {
9351cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
9361cb0ef41Sopenharmony_ci  push(ebp);
9371cb0ef41Sopenharmony_ci  mov(ebp, esp);
9381cb0ef41Sopenharmony_ci  if (!StackFrame::IsJavaScript(type)) {
9391cb0ef41Sopenharmony_ci    Push(Immediate(StackFrame::TypeToMarker(type)));
9401cb0ef41Sopenharmony_ci  }
9411cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
9421cb0ef41Sopenharmony_ci  if (type == StackFrame::WASM) Push(kWasmInstanceRegister);
9431cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
9441cb0ef41Sopenharmony_ci}
9451cb0ef41Sopenharmony_ci
9461cb0ef41Sopenharmony_civoid TurboAssembler::LeaveFrame(StackFrame::Type type) {
9471cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
9481cb0ef41Sopenharmony_ci  if (FLAG_debug_code && !StackFrame::IsJavaScript(type)) {
9491cb0ef41Sopenharmony_ci    cmp(Operand(ebp, CommonFrameConstants::kContextOrFrameTypeOffset),
9501cb0ef41Sopenharmony_ci        Immediate(StackFrame::TypeToMarker(type)));
9511cb0ef41Sopenharmony_ci    Check(equal, AbortReason::kStackFrameTypesMustMatch);
9521cb0ef41Sopenharmony_ci  }
9531cb0ef41Sopenharmony_ci  leave();
9541cb0ef41Sopenharmony_ci}
9551cb0ef41Sopenharmony_ci
9561cb0ef41Sopenharmony_ci#ifdef V8_OS_WIN
9571cb0ef41Sopenharmony_civoid TurboAssembler::AllocateStackSpace(Register bytes_scratch) {
9581cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
9591cb0ef41Sopenharmony_ci  // In windows, we cannot increment the stack size by more than one page
9601cb0ef41Sopenharmony_ci  // (minimum page size is 4KB) without accessing at least one byte on the
9611cb0ef41Sopenharmony_ci  // page. Check this:
9621cb0ef41Sopenharmony_ci  // https://msdn.microsoft.com/en-us/library/aa227153(v=vs.60).aspx.
9631cb0ef41Sopenharmony_ci  Label check_offset;
9641cb0ef41Sopenharmony_ci  Label touch_next_page;
9651cb0ef41Sopenharmony_ci  jmp(&check_offset);
9661cb0ef41Sopenharmony_ci  bind(&touch_next_page);
9671cb0ef41Sopenharmony_ci  sub(esp, Immediate(kStackPageSize));
9681cb0ef41Sopenharmony_ci  // Just to touch the page, before we increment further.
9691cb0ef41Sopenharmony_ci  mov(Operand(esp, 0), Immediate(0));
9701cb0ef41Sopenharmony_ci  sub(bytes_scratch, Immediate(kStackPageSize));
9711cb0ef41Sopenharmony_ci
9721cb0ef41Sopenharmony_ci  bind(&check_offset);
9731cb0ef41Sopenharmony_ci  cmp(bytes_scratch, kStackPageSize);
9741cb0ef41Sopenharmony_ci  j(greater_equal, &touch_next_page);
9751cb0ef41Sopenharmony_ci
9761cb0ef41Sopenharmony_ci  sub(esp, bytes_scratch);
9771cb0ef41Sopenharmony_ci}
9781cb0ef41Sopenharmony_ci
9791cb0ef41Sopenharmony_civoid TurboAssembler::AllocateStackSpace(int bytes) {
9801cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
9811cb0ef41Sopenharmony_ci  DCHECK_GE(bytes, 0);
9821cb0ef41Sopenharmony_ci  while (bytes >= kStackPageSize) {
9831cb0ef41Sopenharmony_ci    sub(esp, Immediate(kStackPageSize));
9841cb0ef41Sopenharmony_ci    mov(Operand(esp, 0), Immediate(0));
9851cb0ef41Sopenharmony_ci    bytes -= kStackPageSize;
9861cb0ef41Sopenharmony_ci  }
9871cb0ef41Sopenharmony_ci  if (bytes == 0) return;
9881cb0ef41Sopenharmony_ci  sub(esp, Immediate(bytes));
9891cb0ef41Sopenharmony_ci}
9901cb0ef41Sopenharmony_ci#endif
9911cb0ef41Sopenharmony_ci
9921cb0ef41Sopenharmony_civoid MacroAssembler::EnterExitFramePrologue(StackFrame::Type frame_type,
9931cb0ef41Sopenharmony_ci                                            Register scratch) {
9941cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
9951cb0ef41Sopenharmony_ci  DCHECK(frame_type == StackFrame::EXIT ||
9961cb0ef41Sopenharmony_ci         frame_type == StackFrame::BUILTIN_EXIT);
9971cb0ef41Sopenharmony_ci
9981cb0ef41Sopenharmony_ci  // Set up the frame structure on the stack.
9991cb0ef41Sopenharmony_ci  DCHECK_EQ(+2 * kSystemPointerSize, ExitFrameConstants::kCallerSPDisplacement);
10001cb0ef41Sopenharmony_ci  DCHECK_EQ(+1 * kSystemPointerSize, ExitFrameConstants::kCallerPCOffset);
10011cb0ef41Sopenharmony_ci  DCHECK_EQ(0 * kSystemPointerSize, ExitFrameConstants::kCallerFPOffset);
10021cb0ef41Sopenharmony_ci  push(ebp);
10031cb0ef41Sopenharmony_ci  mov(ebp, esp);
10041cb0ef41Sopenharmony_ci
10051cb0ef41Sopenharmony_ci  // Reserve room for entry stack pointer.
10061cb0ef41Sopenharmony_ci  push(Immediate(StackFrame::TypeToMarker(frame_type)));
10071cb0ef41Sopenharmony_ci  DCHECK_EQ(-2 * kSystemPointerSize, ExitFrameConstants::kSPOffset);
10081cb0ef41Sopenharmony_ci  push(Immediate(0));  // Saved entry sp, patched before call.
10091cb0ef41Sopenharmony_ci
10101cb0ef41Sopenharmony_ci  STATIC_ASSERT(edx == kRuntimeCallFunctionRegister);
10111cb0ef41Sopenharmony_ci  STATIC_ASSERT(esi == kContextRegister);
10121cb0ef41Sopenharmony_ci
10131cb0ef41Sopenharmony_ci  // Save the frame pointer and the context in top.
10141cb0ef41Sopenharmony_ci  ExternalReference c_entry_fp_address =
10151cb0ef41Sopenharmony_ci      ExternalReference::Create(IsolateAddressId::kCEntryFPAddress, isolate());
10161cb0ef41Sopenharmony_ci  ExternalReference context_address =
10171cb0ef41Sopenharmony_ci      ExternalReference::Create(IsolateAddressId::kContextAddress, isolate());
10181cb0ef41Sopenharmony_ci  ExternalReference c_function_address =
10191cb0ef41Sopenharmony_ci      ExternalReference::Create(IsolateAddressId::kCFunctionAddress, isolate());
10201cb0ef41Sopenharmony_ci
10211cb0ef41Sopenharmony_ci  DCHECK(!AreAliased(scratch, ebp, esi, edx));
10221cb0ef41Sopenharmony_ci  mov(ExternalReferenceAsOperand(c_entry_fp_address, scratch), ebp);
10231cb0ef41Sopenharmony_ci  mov(ExternalReferenceAsOperand(context_address, scratch), esi);
10241cb0ef41Sopenharmony_ci  mov(ExternalReferenceAsOperand(c_function_address, scratch), edx);
10251cb0ef41Sopenharmony_ci}
10261cb0ef41Sopenharmony_ci
10271cb0ef41Sopenharmony_civoid MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
10281cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
10291cb0ef41Sopenharmony_ci  // Optionally save all XMM registers.
10301cb0ef41Sopenharmony_ci  if (save_doubles) {
10311cb0ef41Sopenharmony_ci    int space =
10321cb0ef41Sopenharmony_ci        XMMRegister::kNumRegisters * kDoubleSize + argc * kSystemPointerSize;
10331cb0ef41Sopenharmony_ci    AllocateStackSpace(space);
10341cb0ef41Sopenharmony_ci    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
10351cb0ef41Sopenharmony_ci    for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
10361cb0ef41Sopenharmony_ci      XMMRegister reg = XMMRegister::from_code(i);
10371cb0ef41Sopenharmony_ci      movsd(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg);
10381cb0ef41Sopenharmony_ci    }
10391cb0ef41Sopenharmony_ci  } else {
10401cb0ef41Sopenharmony_ci    AllocateStackSpace(argc * kSystemPointerSize);
10411cb0ef41Sopenharmony_ci  }
10421cb0ef41Sopenharmony_ci
10431cb0ef41Sopenharmony_ci  // Get the required frame alignment for the OS.
10441cb0ef41Sopenharmony_ci  const int kFrameAlignment = base::OS::ActivationFrameAlignment();
10451cb0ef41Sopenharmony_ci  if (kFrameAlignment > 0) {
10461cb0ef41Sopenharmony_ci    DCHECK(base::bits::IsPowerOfTwo(kFrameAlignment));
10471cb0ef41Sopenharmony_ci    and_(esp, -kFrameAlignment);
10481cb0ef41Sopenharmony_ci  }
10491cb0ef41Sopenharmony_ci
10501cb0ef41Sopenharmony_ci  // Patch the saved entry sp.
10511cb0ef41Sopenharmony_ci  mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp);
10521cb0ef41Sopenharmony_ci}
10531cb0ef41Sopenharmony_ci
10541cb0ef41Sopenharmony_civoid MacroAssembler::EnterExitFrame(int argc, bool save_doubles,
10551cb0ef41Sopenharmony_ci                                    StackFrame::Type frame_type) {
10561cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
10571cb0ef41Sopenharmony_ci  EnterExitFramePrologue(frame_type, edi);
10581cb0ef41Sopenharmony_ci
10591cb0ef41Sopenharmony_ci  // Set up argc and argv in callee-saved registers.
10601cb0ef41Sopenharmony_ci  int offset = StandardFrameConstants::kCallerSPOffset - kSystemPointerSize;
10611cb0ef41Sopenharmony_ci  mov(edi, eax);
10621cb0ef41Sopenharmony_ci  lea(esi, Operand(ebp, eax, times_system_pointer_size, offset));
10631cb0ef41Sopenharmony_ci
10641cb0ef41Sopenharmony_ci  // Reserve space for argc, argv and isolate.
10651cb0ef41Sopenharmony_ci  EnterExitFrameEpilogue(argc, save_doubles);
10661cb0ef41Sopenharmony_ci}
10671cb0ef41Sopenharmony_ci
10681cb0ef41Sopenharmony_civoid MacroAssembler::EnterApiExitFrame(int argc, Register scratch) {
10691cb0ef41Sopenharmony_ci  EnterExitFramePrologue(StackFrame::EXIT, scratch);
10701cb0ef41Sopenharmony_ci  EnterExitFrameEpilogue(argc, false);
10711cb0ef41Sopenharmony_ci}
10721cb0ef41Sopenharmony_ci
10731cb0ef41Sopenharmony_civoid MacroAssembler::LeaveExitFrame(bool save_doubles, bool pop_arguments) {
10741cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
10751cb0ef41Sopenharmony_ci  // Optionally restore all XMM registers.
10761cb0ef41Sopenharmony_ci  if (save_doubles) {
10771cb0ef41Sopenharmony_ci    const int offset = -ExitFrameConstants::kFixedFrameSizeFromFp;
10781cb0ef41Sopenharmony_ci    for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
10791cb0ef41Sopenharmony_ci      XMMRegister reg = XMMRegister::from_code(i);
10801cb0ef41Sopenharmony_ci      movsd(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize)));
10811cb0ef41Sopenharmony_ci    }
10821cb0ef41Sopenharmony_ci  }
10831cb0ef41Sopenharmony_ci
10841cb0ef41Sopenharmony_ci  if (pop_arguments) {
10851cb0ef41Sopenharmony_ci    // Get the return address from the stack and restore the frame pointer.
10861cb0ef41Sopenharmony_ci    mov(ecx, Operand(ebp, 1 * kSystemPointerSize));
10871cb0ef41Sopenharmony_ci    mov(ebp, Operand(ebp, 0 * kSystemPointerSize));
10881cb0ef41Sopenharmony_ci
10891cb0ef41Sopenharmony_ci    // Pop the arguments and the receiver from the caller stack.
10901cb0ef41Sopenharmony_ci    lea(esp, Operand(esi, 1 * kSystemPointerSize));
10911cb0ef41Sopenharmony_ci
10921cb0ef41Sopenharmony_ci    // Push the return address to get ready to return.
10931cb0ef41Sopenharmony_ci    push(ecx);
10941cb0ef41Sopenharmony_ci  } else {
10951cb0ef41Sopenharmony_ci    // Otherwise just leave the exit frame.
10961cb0ef41Sopenharmony_ci    leave();
10971cb0ef41Sopenharmony_ci  }
10981cb0ef41Sopenharmony_ci
10991cb0ef41Sopenharmony_ci  LeaveExitFrameEpilogue();
11001cb0ef41Sopenharmony_ci}
11011cb0ef41Sopenharmony_ci
11021cb0ef41Sopenharmony_civoid MacroAssembler::LeaveExitFrameEpilogue() {
11031cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
11041cb0ef41Sopenharmony_ci  // Clear the top frame.
11051cb0ef41Sopenharmony_ci  ExternalReference c_entry_fp_address =
11061cb0ef41Sopenharmony_ci      ExternalReference::Create(IsolateAddressId::kCEntryFPAddress, isolate());
11071cb0ef41Sopenharmony_ci  mov(ExternalReferenceAsOperand(c_entry_fp_address, esi), Immediate(0));
11081cb0ef41Sopenharmony_ci
11091cb0ef41Sopenharmony_ci  // Restore current context from top and clear it in debug mode.
11101cb0ef41Sopenharmony_ci  ExternalReference context_address =
11111cb0ef41Sopenharmony_ci      ExternalReference::Create(IsolateAddressId::kContextAddress, isolate());
11121cb0ef41Sopenharmony_ci  mov(esi, ExternalReferenceAsOperand(context_address, esi));
11131cb0ef41Sopenharmony_ci#ifdef DEBUG
11141cb0ef41Sopenharmony_ci  push(eax);
11151cb0ef41Sopenharmony_ci  mov(ExternalReferenceAsOperand(context_address, eax),
11161cb0ef41Sopenharmony_ci      Immediate(Context::kInvalidContext));
11171cb0ef41Sopenharmony_ci  pop(eax);
11181cb0ef41Sopenharmony_ci#endif
11191cb0ef41Sopenharmony_ci}
11201cb0ef41Sopenharmony_ci
11211cb0ef41Sopenharmony_civoid MacroAssembler::LeaveApiExitFrame() {
11221cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
11231cb0ef41Sopenharmony_ci  mov(esp, ebp);
11241cb0ef41Sopenharmony_ci  pop(ebp);
11251cb0ef41Sopenharmony_ci
11261cb0ef41Sopenharmony_ci  LeaveExitFrameEpilogue();
11271cb0ef41Sopenharmony_ci}
11281cb0ef41Sopenharmony_ci
11291cb0ef41Sopenharmony_civoid MacroAssembler::PushStackHandler(Register scratch) {
11301cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
11311cb0ef41Sopenharmony_ci  // Adjust this code if not the case.
11321cb0ef41Sopenharmony_ci  STATIC_ASSERT(StackHandlerConstants::kSize == 2 * kSystemPointerSize);
11331cb0ef41Sopenharmony_ci  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
11341cb0ef41Sopenharmony_ci
11351cb0ef41Sopenharmony_ci  push(Immediate(0));  // Padding.
11361cb0ef41Sopenharmony_ci
11371cb0ef41Sopenharmony_ci  // Link the current handler as the next handler.
11381cb0ef41Sopenharmony_ci  ExternalReference handler_address =
11391cb0ef41Sopenharmony_ci      ExternalReference::Create(IsolateAddressId::kHandlerAddress, isolate());
11401cb0ef41Sopenharmony_ci  push(ExternalReferenceAsOperand(handler_address, scratch));
11411cb0ef41Sopenharmony_ci
11421cb0ef41Sopenharmony_ci  // Set this new handler as the current one.
11431cb0ef41Sopenharmony_ci  mov(ExternalReferenceAsOperand(handler_address, scratch), esp);
11441cb0ef41Sopenharmony_ci}
11451cb0ef41Sopenharmony_ci
11461cb0ef41Sopenharmony_civoid MacroAssembler::PopStackHandler(Register scratch) {
11471cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
11481cb0ef41Sopenharmony_ci  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
11491cb0ef41Sopenharmony_ci  ExternalReference handler_address =
11501cb0ef41Sopenharmony_ci      ExternalReference::Create(IsolateAddressId::kHandlerAddress, isolate());
11511cb0ef41Sopenharmony_ci  pop(ExternalReferenceAsOperand(handler_address, scratch));
11521cb0ef41Sopenharmony_ci  add(esp, Immediate(StackHandlerConstants::kSize - kSystemPointerSize));
11531cb0ef41Sopenharmony_ci}
11541cb0ef41Sopenharmony_ci
11551cb0ef41Sopenharmony_civoid MacroAssembler::CallRuntime(const Runtime::Function* f, int num_arguments,
11561cb0ef41Sopenharmony_ci                                 SaveFPRegsMode save_doubles) {
11571cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
11581cb0ef41Sopenharmony_ci  // If the expected number of arguments of the runtime function is
11591cb0ef41Sopenharmony_ci  // constant, we check that the actual number of arguments match the
11601cb0ef41Sopenharmony_ci  // expectation.
11611cb0ef41Sopenharmony_ci  CHECK(f->nargs < 0 || f->nargs == num_arguments);
11621cb0ef41Sopenharmony_ci
11631cb0ef41Sopenharmony_ci  // TODO(1236192): Most runtime routines don't need the number of
11641cb0ef41Sopenharmony_ci  // arguments passed in because it is constant. At some point we
11651cb0ef41Sopenharmony_ci  // should remove this need and make the runtime routine entry code
11661cb0ef41Sopenharmony_ci  // smarter.
11671cb0ef41Sopenharmony_ci  Move(kRuntimeCallArgCountRegister, Immediate(num_arguments));
11681cb0ef41Sopenharmony_ci  Move(kRuntimeCallFunctionRegister, Immediate(ExternalReference::Create(f)));
11691cb0ef41Sopenharmony_ci  Handle<Code> code =
11701cb0ef41Sopenharmony_ci      CodeFactory::CEntry(isolate(), f->result_size, save_doubles);
11711cb0ef41Sopenharmony_ci  Call(code, RelocInfo::CODE_TARGET);
11721cb0ef41Sopenharmony_ci}
11731cb0ef41Sopenharmony_ci
11741cb0ef41Sopenharmony_civoid MacroAssembler::TailCallRuntime(Runtime::FunctionId fid) {
11751cb0ef41Sopenharmony_ci  // ----------- S t a t e -------------
11761cb0ef41Sopenharmony_ci  //  -- esp[0]                 : return address
11771cb0ef41Sopenharmony_ci  //  -- esp[8]                 : argument num_arguments - 1
11781cb0ef41Sopenharmony_ci  //  ...
11791cb0ef41Sopenharmony_ci  //  -- esp[8 * num_arguments] : argument 0 (receiver)
11801cb0ef41Sopenharmony_ci  //
11811cb0ef41Sopenharmony_ci  //  For runtime functions with variable arguments:
11821cb0ef41Sopenharmony_ci  //  -- eax                    : number of  arguments
11831cb0ef41Sopenharmony_ci  // -----------------------------------
11841cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
11851cb0ef41Sopenharmony_ci  const Runtime::Function* function = Runtime::FunctionForId(fid);
11861cb0ef41Sopenharmony_ci  DCHECK_EQ(1, function->result_size);
11871cb0ef41Sopenharmony_ci  if (function->nargs >= 0) {
11881cb0ef41Sopenharmony_ci    // TODO(1236192): Most runtime routines don't need the number of
11891cb0ef41Sopenharmony_ci    // arguments passed in because it is constant. At some point we
11901cb0ef41Sopenharmony_ci    // should remove this need and make the runtime routine entry code
11911cb0ef41Sopenharmony_ci    // smarter.
11921cb0ef41Sopenharmony_ci    Move(kRuntimeCallArgCountRegister, Immediate(function->nargs));
11931cb0ef41Sopenharmony_ci  }
11941cb0ef41Sopenharmony_ci  JumpToExternalReference(ExternalReference::Create(fid));
11951cb0ef41Sopenharmony_ci}
11961cb0ef41Sopenharmony_ci
11971cb0ef41Sopenharmony_civoid MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
11981cb0ef41Sopenharmony_ci                                             bool builtin_exit_frame) {
11991cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
12001cb0ef41Sopenharmony_ci  // Set the entry point and jump to the C entry runtime stub.
12011cb0ef41Sopenharmony_ci  Move(kRuntimeCallFunctionRegister, Immediate(ext));
12021cb0ef41Sopenharmony_ci  Handle<Code> code = CodeFactory::CEntry(isolate(), 1, SaveFPRegsMode::kIgnore,
12031cb0ef41Sopenharmony_ci                                          ArgvMode::kStack, builtin_exit_frame);
12041cb0ef41Sopenharmony_ci  Jump(code, RelocInfo::CODE_TARGET);
12051cb0ef41Sopenharmony_ci}
12061cb0ef41Sopenharmony_ci
12071cb0ef41Sopenharmony_civoid MacroAssembler::JumpToOffHeapInstructionStream(Address entry) {
12081cb0ef41Sopenharmony_ci  jmp(entry, RelocInfo::OFF_HEAP_TARGET);
12091cb0ef41Sopenharmony_ci}
12101cb0ef41Sopenharmony_ci
12111cb0ef41Sopenharmony_civoid MacroAssembler::CompareStackLimit(Register with, StackLimitKind kind) {
12121cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
12131cb0ef41Sopenharmony_ci  DCHECK(root_array_available());
12141cb0ef41Sopenharmony_ci  Isolate* isolate = this->isolate();
12151cb0ef41Sopenharmony_ci  // Address through the root register. No load is needed.
12161cb0ef41Sopenharmony_ci  ExternalReference limit =
12171cb0ef41Sopenharmony_ci      kind == StackLimitKind::kRealStackLimit
12181cb0ef41Sopenharmony_ci          ? ExternalReference::address_of_real_jslimit(isolate)
12191cb0ef41Sopenharmony_ci          : ExternalReference::address_of_jslimit(isolate);
12201cb0ef41Sopenharmony_ci  DCHECK(TurboAssembler::IsAddressableThroughRootRegister(isolate, limit));
12211cb0ef41Sopenharmony_ci
12221cb0ef41Sopenharmony_ci  intptr_t offset =
12231cb0ef41Sopenharmony_ci      TurboAssembler::RootRegisterOffsetForExternalReference(isolate, limit);
12241cb0ef41Sopenharmony_ci  cmp(with, Operand(kRootRegister, offset));
12251cb0ef41Sopenharmony_ci}
12261cb0ef41Sopenharmony_ci
12271cb0ef41Sopenharmony_civoid MacroAssembler::StackOverflowCheck(Register num_args, Register scratch,
12281cb0ef41Sopenharmony_ci                                        Label* stack_overflow,
12291cb0ef41Sopenharmony_ci                                        bool include_receiver) {
12301cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
12311cb0ef41Sopenharmony_ci  DCHECK_NE(num_args, scratch);
12321cb0ef41Sopenharmony_ci  // Check the stack for overflow. We are not trying to catch
12331cb0ef41Sopenharmony_ci  // interruptions (e.g. debug break and preemption) here, so the "real stack
12341cb0ef41Sopenharmony_ci  // limit" is checked.
12351cb0ef41Sopenharmony_ci  ExternalReference real_stack_limit =
12361cb0ef41Sopenharmony_ci      ExternalReference::address_of_real_jslimit(isolate());
12371cb0ef41Sopenharmony_ci  // Compute the space that is left as a negative number in scratch. If
12381cb0ef41Sopenharmony_ci  // we already overflowed, this will be a positive number.
12391cb0ef41Sopenharmony_ci  mov(scratch, ExternalReferenceAsOperand(real_stack_limit, scratch));
12401cb0ef41Sopenharmony_ci  sub(scratch, esp);
12411cb0ef41Sopenharmony_ci  // TODO(victorgomes): Remove {include_receiver} and always require one extra
12421cb0ef41Sopenharmony_ci  // word of the stack space.
12431cb0ef41Sopenharmony_ci  lea(scratch, Operand(scratch, num_args, times_system_pointer_size, 0));
12441cb0ef41Sopenharmony_ci  if (include_receiver) {
12451cb0ef41Sopenharmony_ci    add(scratch, Immediate(kSystemPointerSize));
12461cb0ef41Sopenharmony_ci  }
12471cb0ef41Sopenharmony_ci  // See if we overflowed, i.e. scratch is positive.
12481cb0ef41Sopenharmony_ci  cmp(scratch, Immediate(0));
12491cb0ef41Sopenharmony_ci  // TODO(victorgomes):  Save some bytes in the builtins that use stack checks
12501cb0ef41Sopenharmony_ci  // by jumping to a builtin that throws the exception.
12511cb0ef41Sopenharmony_ci  j(greater, stack_overflow);  // Signed comparison.
12521cb0ef41Sopenharmony_ci}
12531cb0ef41Sopenharmony_ci
12541cb0ef41Sopenharmony_civoid MacroAssembler::InvokePrologue(Register expected_parameter_count,
12551cb0ef41Sopenharmony_ci                                    Register actual_parameter_count,
12561cb0ef41Sopenharmony_ci                                    Label* done, InvokeType type) {
12571cb0ef41Sopenharmony_ci  if (expected_parameter_count == actual_parameter_count) return;
12581cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
12591cb0ef41Sopenharmony_ci  DCHECK_EQ(actual_parameter_count, eax);
12601cb0ef41Sopenharmony_ci  DCHECK_EQ(expected_parameter_count, ecx);
12611cb0ef41Sopenharmony_ci  Label regular_invoke;
12621cb0ef41Sopenharmony_ci
12631cb0ef41Sopenharmony_ci  // If the expected parameter count is equal to the adaptor sentinel, no need
12641cb0ef41Sopenharmony_ci  // to push undefined value as arguments.
12651cb0ef41Sopenharmony_ci  if (kDontAdaptArgumentsSentinel != 0) {
12661cb0ef41Sopenharmony_ci    cmp(expected_parameter_count, Immediate(kDontAdaptArgumentsSentinel));
12671cb0ef41Sopenharmony_ci    j(equal, &regular_invoke, Label::kFar);
12681cb0ef41Sopenharmony_ci  }
12691cb0ef41Sopenharmony_ci
12701cb0ef41Sopenharmony_ci  // If overapplication or if the actual argument count is equal to the
12711cb0ef41Sopenharmony_ci  // formal parameter count, no need to push extra undefined values.
12721cb0ef41Sopenharmony_ci  sub(expected_parameter_count, actual_parameter_count);
12731cb0ef41Sopenharmony_ci  j(less_equal, &regular_invoke, Label::kFar);
12741cb0ef41Sopenharmony_ci
12751cb0ef41Sopenharmony_ci  // We need to preserve edx, edi, esi and ebx.
12761cb0ef41Sopenharmony_ci  movd(xmm0, edx);
12771cb0ef41Sopenharmony_ci  movd(xmm1, edi);
12781cb0ef41Sopenharmony_ci  movd(xmm2, esi);
12791cb0ef41Sopenharmony_ci  movd(xmm3, ebx);
12801cb0ef41Sopenharmony_ci
12811cb0ef41Sopenharmony_ci  Label stack_overflow;
12821cb0ef41Sopenharmony_ci  StackOverflowCheck(expected_parameter_count, edx, &stack_overflow);
12831cb0ef41Sopenharmony_ci
12841cb0ef41Sopenharmony_ci  Register scratch = esi;
12851cb0ef41Sopenharmony_ci
12861cb0ef41Sopenharmony_ci  // Underapplication. Move the arguments already in the stack, including the
12871cb0ef41Sopenharmony_ci  // receiver and the return address.
12881cb0ef41Sopenharmony_ci  {
12891cb0ef41Sopenharmony_ci    Label copy, check;
12901cb0ef41Sopenharmony_ci    Register src = edx, dest = esp, num = edi, current = ebx;
12911cb0ef41Sopenharmony_ci    mov(src, esp);
12921cb0ef41Sopenharmony_ci    lea(scratch,
12931cb0ef41Sopenharmony_ci        Operand(expected_parameter_count, times_system_pointer_size, 0));
12941cb0ef41Sopenharmony_ci    AllocateStackSpace(scratch);
12951cb0ef41Sopenharmony_ci    // Extra words are the receiver (if not already included in argc) and the
12961cb0ef41Sopenharmony_ci    // return address (if a jump).
12971cb0ef41Sopenharmony_ci    int extra_words = type == InvokeType::kCall ? 0 : 1;
12981cb0ef41Sopenharmony_ci    lea(num, Operand(eax, extra_words));  // Number of words to copy.
12991cb0ef41Sopenharmony_ci    Move(current, 0);
13001cb0ef41Sopenharmony_ci    // Fall-through to the loop body because there are non-zero words to copy.
13011cb0ef41Sopenharmony_ci    bind(&copy);
13021cb0ef41Sopenharmony_ci    mov(scratch, Operand(src, current, times_system_pointer_size, 0));
13031cb0ef41Sopenharmony_ci    mov(Operand(dest, current, times_system_pointer_size, 0), scratch);
13041cb0ef41Sopenharmony_ci    inc(current);
13051cb0ef41Sopenharmony_ci    bind(&check);
13061cb0ef41Sopenharmony_ci    cmp(current, num);
13071cb0ef41Sopenharmony_ci    j(less, &copy);
13081cb0ef41Sopenharmony_ci    lea(edx, Operand(esp, num, times_system_pointer_size, 0));
13091cb0ef41Sopenharmony_ci  }
13101cb0ef41Sopenharmony_ci
13111cb0ef41Sopenharmony_ci    // Fill remaining expected arguments with undefined values.
13121cb0ef41Sopenharmony_ci    movd(ebx, xmm3);  // Restore root.
13131cb0ef41Sopenharmony_ci    LoadRoot(scratch, RootIndex::kUndefinedValue);
13141cb0ef41Sopenharmony_ci    {
13151cb0ef41Sopenharmony_ci      Label loop;
13161cb0ef41Sopenharmony_ci      bind(&loop);
13171cb0ef41Sopenharmony_ci      dec(expected_parameter_count);
13181cb0ef41Sopenharmony_ci      mov(Operand(edx, expected_parameter_count, times_system_pointer_size, 0),
13191cb0ef41Sopenharmony_ci          scratch);
13201cb0ef41Sopenharmony_ci      j(greater, &loop, Label::kNear);
13211cb0ef41Sopenharmony_ci    }
13221cb0ef41Sopenharmony_ci
13231cb0ef41Sopenharmony_ci    // Restore remaining registers.
13241cb0ef41Sopenharmony_ci    movd(esi, xmm2);
13251cb0ef41Sopenharmony_ci    movd(edi, xmm1);
13261cb0ef41Sopenharmony_ci    movd(edx, xmm0);
13271cb0ef41Sopenharmony_ci
13281cb0ef41Sopenharmony_ci    jmp(&regular_invoke);
13291cb0ef41Sopenharmony_ci
13301cb0ef41Sopenharmony_ci    bind(&stack_overflow);
13311cb0ef41Sopenharmony_ci    {
13321cb0ef41Sopenharmony_ci      FrameScope frame(
13331cb0ef41Sopenharmony_ci          this, has_frame() ? StackFrame::NO_FRAME_TYPE : StackFrame::INTERNAL);
13341cb0ef41Sopenharmony_ci      CallRuntime(Runtime::kThrowStackOverflow);
13351cb0ef41Sopenharmony_ci      int3();  // This should be unreachable.
13361cb0ef41Sopenharmony_ci    }
13371cb0ef41Sopenharmony_ci
13381cb0ef41Sopenharmony_ci    bind(&regular_invoke);
13391cb0ef41Sopenharmony_ci}
13401cb0ef41Sopenharmony_ci
13411cb0ef41Sopenharmony_civoid MacroAssembler::CallDebugOnFunctionCall(Register fun, Register new_target,
13421cb0ef41Sopenharmony_ci                                             Register expected_parameter_count,
13431cb0ef41Sopenharmony_ci                                             Register actual_parameter_count) {
13441cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
13451cb0ef41Sopenharmony_ci  FrameScope frame(
13461cb0ef41Sopenharmony_ci      this, has_frame() ? StackFrame::NO_FRAME_TYPE : StackFrame::INTERNAL);
13471cb0ef41Sopenharmony_ci  SmiTag(expected_parameter_count);
13481cb0ef41Sopenharmony_ci  Push(expected_parameter_count);
13491cb0ef41Sopenharmony_ci
13501cb0ef41Sopenharmony_ci  SmiTag(actual_parameter_count);
13511cb0ef41Sopenharmony_ci  Push(actual_parameter_count);
13521cb0ef41Sopenharmony_ci  SmiUntag(actual_parameter_count);
13531cb0ef41Sopenharmony_ci
13541cb0ef41Sopenharmony_ci  if (new_target.is_valid()) {
13551cb0ef41Sopenharmony_ci    Push(new_target);
13561cb0ef41Sopenharmony_ci  }
13571cb0ef41Sopenharmony_ci  Push(fun);
13581cb0ef41Sopenharmony_ci  Push(fun);
13591cb0ef41Sopenharmony_ci  // Arguments are located 2 words below the base pointer.
13601cb0ef41Sopenharmony_ci  Operand receiver_op = Operand(ebp, kSystemPointerSize * 2);
13611cb0ef41Sopenharmony_ci  Push(receiver_op);
13621cb0ef41Sopenharmony_ci  CallRuntime(Runtime::kDebugOnFunctionCall);
13631cb0ef41Sopenharmony_ci  Pop(fun);
13641cb0ef41Sopenharmony_ci  if (new_target.is_valid()) {
13651cb0ef41Sopenharmony_ci    Pop(new_target);
13661cb0ef41Sopenharmony_ci  }
13671cb0ef41Sopenharmony_ci  Pop(actual_parameter_count);
13681cb0ef41Sopenharmony_ci  SmiUntag(actual_parameter_count);
13691cb0ef41Sopenharmony_ci
13701cb0ef41Sopenharmony_ci  Pop(expected_parameter_count);
13711cb0ef41Sopenharmony_ci  SmiUntag(expected_parameter_count);
13721cb0ef41Sopenharmony_ci}
13731cb0ef41Sopenharmony_ci
13741cb0ef41Sopenharmony_civoid MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
13751cb0ef41Sopenharmony_ci                                        Register expected_parameter_count,
13761cb0ef41Sopenharmony_ci                                        Register actual_parameter_count,
13771cb0ef41Sopenharmony_ci                                        InvokeType type) {
13781cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
13791cb0ef41Sopenharmony_ci  // You can't call a function without a valid frame.
13801cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(type == InvokeType::kCall, has_frame());
13811cb0ef41Sopenharmony_ci  DCHECK_EQ(function, edi);
13821cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(new_target.is_valid(), new_target == edx);
13831cb0ef41Sopenharmony_ci  DCHECK(expected_parameter_count == ecx || expected_parameter_count == eax);
13841cb0ef41Sopenharmony_ci  DCHECK_EQ(actual_parameter_count, eax);
13851cb0ef41Sopenharmony_ci
13861cb0ef41Sopenharmony_ci  // On function call, call into the debugger if necessary.
13871cb0ef41Sopenharmony_ci  Label debug_hook, continue_after_hook;
13881cb0ef41Sopenharmony_ci  {
13891cb0ef41Sopenharmony_ci    ExternalReference debug_hook_active =
13901cb0ef41Sopenharmony_ci        ExternalReference::debug_hook_on_function_call_address(isolate());
13911cb0ef41Sopenharmony_ci    push(eax);
13921cb0ef41Sopenharmony_ci    cmpb(ExternalReferenceAsOperand(debug_hook_active, eax), Immediate(0));
13931cb0ef41Sopenharmony_ci    pop(eax);
13941cb0ef41Sopenharmony_ci    j(not_equal, &debug_hook);
13951cb0ef41Sopenharmony_ci  }
13961cb0ef41Sopenharmony_ci  bind(&continue_after_hook);
13971cb0ef41Sopenharmony_ci
13981cb0ef41Sopenharmony_ci  // Clear the new.target register if not given.
13991cb0ef41Sopenharmony_ci  if (!new_target.is_valid()) {
14001cb0ef41Sopenharmony_ci    Move(edx, isolate()->factory()->undefined_value());
14011cb0ef41Sopenharmony_ci  }
14021cb0ef41Sopenharmony_ci
14031cb0ef41Sopenharmony_ci  Label done;
14041cb0ef41Sopenharmony_ci  InvokePrologue(expected_parameter_count, actual_parameter_count, &done, type);
14051cb0ef41Sopenharmony_ci  // We call indirectly through the code field in the function to
14061cb0ef41Sopenharmony_ci  // allow recompilation to take effect without changing any of the
14071cb0ef41Sopenharmony_ci  // call sites.
14081cb0ef41Sopenharmony_ci  static_assert(kJavaScriptCallCodeStartRegister == ecx, "ABI mismatch");
14091cb0ef41Sopenharmony_ci  mov(ecx, FieldOperand(function, JSFunction::kCodeOffset));
14101cb0ef41Sopenharmony_ci  switch (type) {
14111cb0ef41Sopenharmony_ci    case InvokeType::kCall:
14121cb0ef41Sopenharmony_ci      CallCodeObject(ecx);
14131cb0ef41Sopenharmony_ci      break;
14141cb0ef41Sopenharmony_ci    case InvokeType::kJump:
14151cb0ef41Sopenharmony_ci      JumpCodeObject(ecx);
14161cb0ef41Sopenharmony_ci      break;
14171cb0ef41Sopenharmony_ci  }
14181cb0ef41Sopenharmony_ci  jmp(&done, Label::kNear);
14191cb0ef41Sopenharmony_ci
14201cb0ef41Sopenharmony_ci  // Deferred debug hook.
14211cb0ef41Sopenharmony_ci  bind(&debug_hook);
14221cb0ef41Sopenharmony_ci  CallDebugOnFunctionCall(function, new_target, expected_parameter_count,
14231cb0ef41Sopenharmony_ci                          actual_parameter_count);
14241cb0ef41Sopenharmony_ci  jmp(&continue_after_hook);
14251cb0ef41Sopenharmony_ci
14261cb0ef41Sopenharmony_ci  bind(&done);
14271cb0ef41Sopenharmony_ci}
14281cb0ef41Sopenharmony_ci
14291cb0ef41Sopenharmony_civoid MacroAssembler::InvokeFunction(Register fun, Register new_target,
14301cb0ef41Sopenharmony_ci                                    Register actual_parameter_count,
14311cb0ef41Sopenharmony_ci                                    InvokeType type) {
14321cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
14331cb0ef41Sopenharmony_ci  // You can't call a function without a valid frame.
14341cb0ef41Sopenharmony_ci  DCHECK(type == InvokeType::kJump || has_frame());
14351cb0ef41Sopenharmony_ci
14361cb0ef41Sopenharmony_ci  DCHECK(fun == edi);
14371cb0ef41Sopenharmony_ci  mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
14381cb0ef41Sopenharmony_ci  mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
14391cb0ef41Sopenharmony_ci  movzx_w(ecx,
14401cb0ef41Sopenharmony_ci          FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset));
14411cb0ef41Sopenharmony_ci
14421cb0ef41Sopenharmony_ci  InvokeFunctionCode(edi, new_target, ecx, actual_parameter_count, type);
14431cb0ef41Sopenharmony_ci}
14441cb0ef41Sopenharmony_ci
14451cb0ef41Sopenharmony_civoid MacroAssembler::LoadGlobalProxy(Register dst) {
14461cb0ef41Sopenharmony_ci  LoadNativeContextSlot(dst, Context::GLOBAL_PROXY_INDEX);
14471cb0ef41Sopenharmony_ci}
14481cb0ef41Sopenharmony_ci
14491cb0ef41Sopenharmony_civoid MacroAssembler::LoadNativeContextSlot(Register destination, int index) {
14501cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
14511cb0ef41Sopenharmony_ci  // Load the native context from the current context.
14521cb0ef41Sopenharmony_ci  LoadMap(destination, esi);
14531cb0ef41Sopenharmony_ci  mov(destination,
14541cb0ef41Sopenharmony_ci      FieldOperand(destination,
14551cb0ef41Sopenharmony_ci                   Map::kConstructorOrBackPointerOrNativeContextOffset));
14561cb0ef41Sopenharmony_ci  // Load the function from the native context.
14571cb0ef41Sopenharmony_ci  mov(destination, Operand(destination, Context::SlotOffset(index)));
14581cb0ef41Sopenharmony_ci}
14591cb0ef41Sopenharmony_ci
14601cb0ef41Sopenharmony_civoid TurboAssembler::Ret() { ret(0); }
14611cb0ef41Sopenharmony_ci
14621cb0ef41Sopenharmony_civoid TurboAssembler::Ret(int bytes_dropped, Register scratch) {
14631cb0ef41Sopenharmony_ci  if (is_uint16(bytes_dropped)) {
14641cb0ef41Sopenharmony_ci    ret(bytes_dropped);
14651cb0ef41Sopenharmony_ci  } else {
14661cb0ef41Sopenharmony_ci    pop(scratch);
14671cb0ef41Sopenharmony_ci    add(esp, Immediate(bytes_dropped));
14681cb0ef41Sopenharmony_ci    push(scratch);
14691cb0ef41Sopenharmony_ci    ret(0);
14701cb0ef41Sopenharmony_ci  }
14711cb0ef41Sopenharmony_ci}
14721cb0ef41Sopenharmony_ci
14731cb0ef41Sopenharmony_civoid TurboAssembler::Push(Immediate value) {
14741cb0ef41Sopenharmony_ci  if (root_array_available() && options().isolate_independent_code) {
14751cb0ef41Sopenharmony_ci    if (value.is_embedded_object()) {
14761cb0ef41Sopenharmony_ci      Push(HeapObjectAsOperand(value.embedded_object()));
14771cb0ef41Sopenharmony_ci      return;
14781cb0ef41Sopenharmony_ci    } else if (value.is_external_reference()) {
14791cb0ef41Sopenharmony_ci      Push(ExternalReferenceAddressAsOperand(value.external_reference()));
14801cb0ef41Sopenharmony_ci      return;
14811cb0ef41Sopenharmony_ci    }
14821cb0ef41Sopenharmony_ci  }
14831cb0ef41Sopenharmony_ci  push(value);
14841cb0ef41Sopenharmony_ci}
14851cb0ef41Sopenharmony_ci
14861cb0ef41Sopenharmony_civoid MacroAssembler::Drop(int stack_elements) {
14871cb0ef41Sopenharmony_ci  if (stack_elements > 0) {
14881cb0ef41Sopenharmony_ci    add(esp, Immediate(stack_elements * kSystemPointerSize));
14891cb0ef41Sopenharmony_ci  }
14901cb0ef41Sopenharmony_ci}
14911cb0ef41Sopenharmony_ci
14921cb0ef41Sopenharmony_civoid TurboAssembler::Move(Register dst, Register src) {
14931cb0ef41Sopenharmony_ci  if (dst != src) {
14941cb0ef41Sopenharmony_ci    mov(dst, src);
14951cb0ef41Sopenharmony_ci  }
14961cb0ef41Sopenharmony_ci}
14971cb0ef41Sopenharmony_ci
14981cb0ef41Sopenharmony_civoid TurboAssembler::Move(Register dst, const Immediate& src) {
14991cb0ef41Sopenharmony_ci  if (!src.is_heap_object_request() && src.is_zero()) {
15001cb0ef41Sopenharmony_ci    xor_(dst, dst);  // Shorter than mov of 32-bit immediate 0.
15011cb0ef41Sopenharmony_ci  } else if (src.is_external_reference()) {
15021cb0ef41Sopenharmony_ci    LoadAddress(dst, src.external_reference());
15031cb0ef41Sopenharmony_ci  } else {
15041cb0ef41Sopenharmony_ci    mov(dst, src);
15051cb0ef41Sopenharmony_ci  }
15061cb0ef41Sopenharmony_ci}
15071cb0ef41Sopenharmony_ci
15081cb0ef41Sopenharmony_civoid TurboAssembler::Move(Operand dst, const Immediate& src) {
15091cb0ef41Sopenharmony_ci  // Since there's no scratch register available, take a detour through the
15101cb0ef41Sopenharmony_ci  // stack.
15111cb0ef41Sopenharmony_ci  if (root_array_available() && options().isolate_independent_code) {
15121cb0ef41Sopenharmony_ci    if (src.is_embedded_object() || src.is_external_reference() ||
15131cb0ef41Sopenharmony_ci        src.is_heap_object_request()) {
15141cb0ef41Sopenharmony_ci      Push(src);
15151cb0ef41Sopenharmony_ci      pop(dst);
15161cb0ef41Sopenharmony_ci      return;
15171cb0ef41Sopenharmony_ci    }
15181cb0ef41Sopenharmony_ci  }
15191cb0ef41Sopenharmony_ci
15201cb0ef41Sopenharmony_ci  if (src.is_embedded_object()) {
15211cb0ef41Sopenharmony_ci    mov(dst, src.embedded_object());
15221cb0ef41Sopenharmony_ci  } else {
15231cb0ef41Sopenharmony_ci    mov(dst, src);
15241cb0ef41Sopenharmony_ci  }
15251cb0ef41Sopenharmony_ci}
15261cb0ef41Sopenharmony_ci
15271cb0ef41Sopenharmony_civoid TurboAssembler::Move(Register dst, Operand src) { mov(dst, src); }
15281cb0ef41Sopenharmony_ci
15291cb0ef41Sopenharmony_civoid TurboAssembler::Move(Register dst, Handle<HeapObject> src) {
15301cb0ef41Sopenharmony_ci  if (root_array_available() && options().isolate_independent_code) {
15311cb0ef41Sopenharmony_ci    IndirectLoadConstant(dst, src);
15321cb0ef41Sopenharmony_ci    return;
15331cb0ef41Sopenharmony_ci  }
15341cb0ef41Sopenharmony_ci  mov(dst, src);
15351cb0ef41Sopenharmony_ci}
15361cb0ef41Sopenharmony_ci
15371cb0ef41Sopenharmony_civoid TurboAssembler::Move(XMMRegister dst, uint32_t src) {
15381cb0ef41Sopenharmony_ci  if (src == 0) {
15391cb0ef41Sopenharmony_ci    pxor(dst, dst);
15401cb0ef41Sopenharmony_ci  } else {
15411cb0ef41Sopenharmony_ci    unsigned cnt = base::bits::CountPopulation(src);
15421cb0ef41Sopenharmony_ci    unsigned nlz = base::bits::CountLeadingZeros32(src);
15431cb0ef41Sopenharmony_ci    unsigned ntz = base::bits::CountTrailingZeros32(src);
15441cb0ef41Sopenharmony_ci    if (nlz + cnt + ntz == 32) {
15451cb0ef41Sopenharmony_ci      pcmpeqd(dst, dst);
15461cb0ef41Sopenharmony_ci      if (ntz == 0) {
15471cb0ef41Sopenharmony_ci        psrld(dst, 32 - cnt);
15481cb0ef41Sopenharmony_ci      } else {
15491cb0ef41Sopenharmony_ci        pslld(dst, 32 - cnt);
15501cb0ef41Sopenharmony_ci        if (nlz != 0) psrld(dst, nlz);
15511cb0ef41Sopenharmony_ci      }
15521cb0ef41Sopenharmony_ci    } else {
15531cb0ef41Sopenharmony_ci      push(eax);
15541cb0ef41Sopenharmony_ci      mov(eax, Immediate(src));
15551cb0ef41Sopenharmony_ci      movd(dst, Operand(eax));
15561cb0ef41Sopenharmony_ci      pop(eax);
15571cb0ef41Sopenharmony_ci    }
15581cb0ef41Sopenharmony_ci  }
15591cb0ef41Sopenharmony_ci}
15601cb0ef41Sopenharmony_ci
15611cb0ef41Sopenharmony_civoid TurboAssembler::Move(XMMRegister dst, uint64_t src) {
15621cb0ef41Sopenharmony_ci  if (src == 0) {
15631cb0ef41Sopenharmony_ci    pxor(dst, dst);
15641cb0ef41Sopenharmony_ci  } else {
15651cb0ef41Sopenharmony_ci    uint32_t lower = static_cast<uint32_t>(src);
15661cb0ef41Sopenharmony_ci    uint32_t upper = static_cast<uint32_t>(src >> 32);
15671cb0ef41Sopenharmony_ci    unsigned cnt = base::bits::CountPopulation(src);
15681cb0ef41Sopenharmony_ci    unsigned nlz = base::bits::CountLeadingZeros64(src);
15691cb0ef41Sopenharmony_ci    unsigned ntz = base::bits::CountTrailingZeros64(src);
15701cb0ef41Sopenharmony_ci    if (nlz + cnt + ntz == 64) {
15711cb0ef41Sopenharmony_ci      pcmpeqd(dst, dst);
15721cb0ef41Sopenharmony_ci      if (ntz == 0) {
15731cb0ef41Sopenharmony_ci        psrlq(dst, 64 - cnt);
15741cb0ef41Sopenharmony_ci      } else {
15751cb0ef41Sopenharmony_ci        psllq(dst, 64 - cnt);
15761cb0ef41Sopenharmony_ci        if (nlz != 0) psrlq(dst, nlz);
15771cb0ef41Sopenharmony_ci      }
15781cb0ef41Sopenharmony_ci    } else if (lower == 0) {
15791cb0ef41Sopenharmony_ci      Move(dst, upper);
15801cb0ef41Sopenharmony_ci      psllq(dst, 32);
15811cb0ef41Sopenharmony_ci    } else if (CpuFeatures::IsSupported(SSE4_1)) {
15821cb0ef41Sopenharmony_ci      CpuFeatureScope scope(this, SSE4_1);
15831cb0ef41Sopenharmony_ci      push(eax);
15841cb0ef41Sopenharmony_ci      Move(eax, Immediate(lower));
15851cb0ef41Sopenharmony_ci      movd(dst, Operand(eax));
15861cb0ef41Sopenharmony_ci      if (upper != lower) {
15871cb0ef41Sopenharmony_ci        Move(eax, Immediate(upper));
15881cb0ef41Sopenharmony_ci      }
15891cb0ef41Sopenharmony_ci      pinsrd(dst, Operand(eax), 1);
15901cb0ef41Sopenharmony_ci      pop(eax);
15911cb0ef41Sopenharmony_ci    } else {
15921cb0ef41Sopenharmony_ci      push(Immediate(upper));
15931cb0ef41Sopenharmony_ci      push(Immediate(lower));
15941cb0ef41Sopenharmony_ci      movsd(dst, Operand(esp, 0));
15951cb0ef41Sopenharmony_ci      add(esp, Immediate(kDoubleSize));
15961cb0ef41Sopenharmony_ci    }
15971cb0ef41Sopenharmony_ci  }
15981cb0ef41Sopenharmony_ci}
15991cb0ef41Sopenharmony_ci
16001cb0ef41Sopenharmony_civoid TurboAssembler::PextrdPreSse41(Register dst, XMMRegister src,
16011cb0ef41Sopenharmony_ci                                    uint8_t imm8) {
16021cb0ef41Sopenharmony_ci  if (imm8 == 0) {
16031cb0ef41Sopenharmony_ci    Movd(dst, src);
16041cb0ef41Sopenharmony_ci    return;
16051cb0ef41Sopenharmony_ci  }
16061cb0ef41Sopenharmony_ci  // Without AVX or SSE, we can only have 64-bit values in xmm registers.
16071cb0ef41Sopenharmony_ci  // We don't have an xmm scratch register, so move the data via the stack. This
16081cb0ef41Sopenharmony_ci  // path is rarely required, so it's acceptable to be slow.
16091cb0ef41Sopenharmony_ci  DCHECK_LT(imm8, 2);
16101cb0ef41Sopenharmony_ci  AllocateStackSpace(kDoubleSize);
16111cb0ef41Sopenharmony_ci  movsd(Operand(esp, 0), src);
16121cb0ef41Sopenharmony_ci  mov(dst, Operand(esp, imm8 * kUInt32Size));
16131cb0ef41Sopenharmony_ci  add(esp, Immediate(kDoubleSize));
16141cb0ef41Sopenharmony_ci}
16151cb0ef41Sopenharmony_ci
16161cb0ef41Sopenharmony_civoid TurboAssembler::PinsrdPreSse41(XMMRegister dst, Operand src, uint8_t imm8,
16171cb0ef41Sopenharmony_ci                                    uint32_t* load_pc_offset) {
16181cb0ef41Sopenharmony_ci  // Without AVX or SSE, we can only have 64-bit values in xmm registers.
16191cb0ef41Sopenharmony_ci  // We don't have an xmm scratch register, so move the data via the stack. This
16201cb0ef41Sopenharmony_ci  // path is rarely required, so it's acceptable to be slow.
16211cb0ef41Sopenharmony_ci  DCHECK_LT(imm8, 2);
16221cb0ef41Sopenharmony_ci  AllocateStackSpace(kDoubleSize);
16231cb0ef41Sopenharmony_ci  // Write original content of {dst} to the stack.
16241cb0ef41Sopenharmony_ci  movsd(Operand(esp, 0), dst);
16251cb0ef41Sopenharmony_ci  // Overwrite the portion specified in {imm8}.
16261cb0ef41Sopenharmony_ci  if (src.is_reg_only()) {
16271cb0ef41Sopenharmony_ci    mov(Operand(esp, imm8 * kUInt32Size), src.reg());
16281cb0ef41Sopenharmony_ci  } else {
16291cb0ef41Sopenharmony_ci    movss(dst, src);
16301cb0ef41Sopenharmony_ci    movss(Operand(esp, imm8 * kUInt32Size), dst);
16311cb0ef41Sopenharmony_ci  }
16321cb0ef41Sopenharmony_ci  // Load back the full value into {dst}.
16331cb0ef41Sopenharmony_ci  movsd(dst, Operand(esp, 0));
16341cb0ef41Sopenharmony_ci  add(esp, Immediate(kDoubleSize));
16351cb0ef41Sopenharmony_ci}
16361cb0ef41Sopenharmony_ci
16371cb0ef41Sopenharmony_civoid TurboAssembler::Lzcnt(Register dst, Operand src) {
16381cb0ef41Sopenharmony_ci  if (CpuFeatures::IsSupported(LZCNT)) {
16391cb0ef41Sopenharmony_ci    CpuFeatureScope scope(this, LZCNT);
16401cb0ef41Sopenharmony_ci    lzcnt(dst, src);
16411cb0ef41Sopenharmony_ci    return;
16421cb0ef41Sopenharmony_ci  }
16431cb0ef41Sopenharmony_ci  Label not_zero_src;
16441cb0ef41Sopenharmony_ci  bsr(dst, src);
16451cb0ef41Sopenharmony_ci  j(not_zero, &not_zero_src, Label::kNear);
16461cb0ef41Sopenharmony_ci  mov(dst, 63);  // 63^31 == 32
16471cb0ef41Sopenharmony_ci  bind(&not_zero_src);
16481cb0ef41Sopenharmony_ci  xor_(dst, Immediate(31));  // for x in [0..31], 31^x == 31-x.
16491cb0ef41Sopenharmony_ci}
16501cb0ef41Sopenharmony_ci
16511cb0ef41Sopenharmony_civoid TurboAssembler::Tzcnt(Register dst, Operand src) {
16521cb0ef41Sopenharmony_ci  if (CpuFeatures::IsSupported(BMI1)) {
16531cb0ef41Sopenharmony_ci    CpuFeatureScope scope(this, BMI1);
16541cb0ef41Sopenharmony_ci    tzcnt(dst, src);
16551cb0ef41Sopenharmony_ci    return;
16561cb0ef41Sopenharmony_ci  }
16571cb0ef41Sopenharmony_ci  Label not_zero_src;
16581cb0ef41Sopenharmony_ci  bsf(dst, src);
16591cb0ef41Sopenharmony_ci  j(not_zero, &not_zero_src, Label::kNear);
16601cb0ef41Sopenharmony_ci  mov(dst, 32);  // The result of tzcnt is 32 if src = 0.
16611cb0ef41Sopenharmony_ci  bind(&not_zero_src);
16621cb0ef41Sopenharmony_ci}
16631cb0ef41Sopenharmony_ci
16641cb0ef41Sopenharmony_civoid TurboAssembler::Popcnt(Register dst, Operand src) {
16651cb0ef41Sopenharmony_ci  if (CpuFeatures::IsSupported(POPCNT)) {
16661cb0ef41Sopenharmony_ci    CpuFeatureScope scope(this, POPCNT);
16671cb0ef41Sopenharmony_ci    popcnt(dst, src);
16681cb0ef41Sopenharmony_ci    return;
16691cb0ef41Sopenharmony_ci  }
16701cb0ef41Sopenharmony_ci  FATAL("no POPCNT support");
16711cb0ef41Sopenharmony_ci}
16721cb0ef41Sopenharmony_ci
16731cb0ef41Sopenharmony_civoid MacroAssembler::LoadWeakValue(Register in_out, Label* target_if_cleared) {
16741cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
16751cb0ef41Sopenharmony_ci  cmp(in_out, Immediate(kClearedWeakHeapObjectLower32));
16761cb0ef41Sopenharmony_ci  j(equal, target_if_cleared);
16771cb0ef41Sopenharmony_ci
16781cb0ef41Sopenharmony_ci  and_(in_out, Immediate(~kWeakHeapObjectMask));
16791cb0ef41Sopenharmony_ci}
16801cb0ef41Sopenharmony_ci
16811cb0ef41Sopenharmony_civoid MacroAssembler::EmitIncrementCounter(StatsCounter* counter, int value,
16821cb0ef41Sopenharmony_ci                                          Register scratch) {
16831cb0ef41Sopenharmony_ci  DCHECK_GT(value, 0);
16841cb0ef41Sopenharmony_ci  if (FLAG_native_code_counters && counter->Enabled()) {
16851cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT(this);
16861cb0ef41Sopenharmony_ci    Operand operand =
16871cb0ef41Sopenharmony_ci        ExternalReferenceAsOperand(ExternalReference::Create(counter), scratch);
16881cb0ef41Sopenharmony_ci    if (value == 1) {
16891cb0ef41Sopenharmony_ci      inc(operand);
16901cb0ef41Sopenharmony_ci    } else {
16911cb0ef41Sopenharmony_ci      add(operand, Immediate(value));
16921cb0ef41Sopenharmony_ci    }
16931cb0ef41Sopenharmony_ci  }
16941cb0ef41Sopenharmony_ci}
16951cb0ef41Sopenharmony_ci
16961cb0ef41Sopenharmony_civoid MacroAssembler::EmitDecrementCounter(StatsCounter* counter, int value,
16971cb0ef41Sopenharmony_ci                                          Register scratch) {
16981cb0ef41Sopenharmony_ci  DCHECK_GT(value, 0);
16991cb0ef41Sopenharmony_ci  if (FLAG_native_code_counters && counter->Enabled()) {
17001cb0ef41Sopenharmony_ci    ASM_CODE_COMMENT(this);
17011cb0ef41Sopenharmony_ci    Operand operand =
17021cb0ef41Sopenharmony_ci        ExternalReferenceAsOperand(ExternalReference::Create(counter), scratch);
17031cb0ef41Sopenharmony_ci    if (value == 1) {
17041cb0ef41Sopenharmony_ci      dec(operand);
17051cb0ef41Sopenharmony_ci    } else {
17061cb0ef41Sopenharmony_ci      sub(operand, Immediate(value));
17071cb0ef41Sopenharmony_ci    }
17081cb0ef41Sopenharmony_ci  }
17091cb0ef41Sopenharmony_ci}
17101cb0ef41Sopenharmony_ci
17111cb0ef41Sopenharmony_civoid TurboAssembler::Assert(Condition cc, AbortReason reason) {
17121cb0ef41Sopenharmony_ci  if (FLAG_debug_code) Check(cc, reason);
17131cb0ef41Sopenharmony_ci}
17141cb0ef41Sopenharmony_ci
17151cb0ef41Sopenharmony_civoid TurboAssembler::AssertUnreachable(AbortReason reason) {
17161cb0ef41Sopenharmony_ci  if (FLAG_debug_code) Abort(reason);
17171cb0ef41Sopenharmony_ci}
17181cb0ef41Sopenharmony_ci
17191cb0ef41Sopenharmony_civoid TurboAssembler::Check(Condition cc, AbortReason reason) {
17201cb0ef41Sopenharmony_ci  Label L;
17211cb0ef41Sopenharmony_ci  j(cc, &L);
17221cb0ef41Sopenharmony_ci  Abort(reason);
17231cb0ef41Sopenharmony_ci  // will not return here
17241cb0ef41Sopenharmony_ci  bind(&L);
17251cb0ef41Sopenharmony_ci}
17261cb0ef41Sopenharmony_ci
17271cb0ef41Sopenharmony_civoid TurboAssembler::CheckStackAlignment() {
17281cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
17291cb0ef41Sopenharmony_ci  int frame_alignment = base::OS::ActivationFrameAlignment();
17301cb0ef41Sopenharmony_ci  int frame_alignment_mask = frame_alignment - 1;
17311cb0ef41Sopenharmony_ci  if (frame_alignment > kSystemPointerSize) {
17321cb0ef41Sopenharmony_ci    DCHECK(base::bits::IsPowerOfTwo(frame_alignment));
17331cb0ef41Sopenharmony_ci    Label alignment_as_expected;
17341cb0ef41Sopenharmony_ci    test(esp, Immediate(frame_alignment_mask));
17351cb0ef41Sopenharmony_ci    j(zero, &alignment_as_expected);
17361cb0ef41Sopenharmony_ci    // Abort if stack is not aligned.
17371cb0ef41Sopenharmony_ci    int3();
17381cb0ef41Sopenharmony_ci    bind(&alignment_as_expected);
17391cb0ef41Sopenharmony_ci  }
17401cb0ef41Sopenharmony_ci}
17411cb0ef41Sopenharmony_ci
17421cb0ef41Sopenharmony_civoid TurboAssembler::Abort(AbortReason reason) {
17431cb0ef41Sopenharmony_ci  if (FLAG_code_comments) {
17441cb0ef41Sopenharmony_ci    const char* msg = GetAbortReason(reason);
17451cb0ef41Sopenharmony_ci    RecordComment("Abort message: ");
17461cb0ef41Sopenharmony_ci    RecordComment(msg);
17471cb0ef41Sopenharmony_ci  }
17481cb0ef41Sopenharmony_ci
17491cb0ef41Sopenharmony_ci  // Avoid emitting call to builtin if requested.
17501cb0ef41Sopenharmony_ci  if (trap_on_abort()) {
17511cb0ef41Sopenharmony_ci    int3();
17521cb0ef41Sopenharmony_ci    return;
17531cb0ef41Sopenharmony_ci  }
17541cb0ef41Sopenharmony_ci
17551cb0ef41Sopenharmony_ci  if (should_abort_hard()) {
17561cb0ef41Sopenharmony_ci    // We don't care if we constructed a frame. Just pretend we did.
17571cb0ef41Sopenharmony_ci    FrameScope assume_frame(this, StackFrame::NO_FRAME_TYPE);
17581cb0ef41Sopenharmony_ci    PrepareCallCFunction(1, eax);
17591cb0ef41Sopenharmony_ci    mov(Operand(esp, 0), Immediate(static_cast<int>(reason)));
17601cb0ef41Sopenharmony_ci    CallCFunction(ExternalReference::abort_with_reason(), 1);
17611cb0ef41Sopenharmony_ci    return;
17621cb0ef41Sopenharmony_ci  }
17631cb0ef41Sopenharmony_ci
17641cb0ef41Sopenharmony_ci  Move(edx, Smi::FromInt(static_cast<int>(reason)));
17651cb0ef41Sopenharmony_ci
17661cb0ef41Sopenharmony_ci  // Disable stub call restrictions to always allow calls to abort.
17671cb0ef41Sopenharmony_ci  if (!has_frame()) {
17681cb0ef41Sopenharmony_ci    // We don't actually want to generate a pile of code for this, so just
17691cb0ef41Sopenharmony_ci    // claim there is a stack frame, without generating one.
17701cb0ef41Sopenharmony_ci    FrameScope scope(this, StackFrame::NO_FRAME_TYPE);
17711cb0ef41Sopenharmony_ci    Call(BUILTIN_CODE(isolate(), Abort), RelocInfo::CODE_TARGET);
17721cb0ef41Sopenharmony_ci  } else {
17731cb0ef41Sopenharmony_ci    Call(BUILTIN_CODE(isolate(), Abort), RelocInfo::CODE_TARGET);
17741cb0ef41Sopenharmony_ci  }
17751cb0ef41Sopenharmony_ci  // will not return here
17761cb0ef41Sopenharmony_ci  int3();
17771cb0ef41Sopenharmony_ci}
17781cb0ef41Sopenharmony_ci
17791cb0ef41Sopenharmony_civoid TurboAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
17801cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
17811cb0ef41Sopenharmony_ci  int frame_alignment = base::OS::ActivationFrameAlignment();
17821cb0ef41Sopenharmony_ci  if (frame_alignment != 0) {
17831cb0ef41Sopenharmony_ci    // Make stack end at alignment and make room for num_arguments words
17841cb0ef41Sopenharmony_ci    // and the original value of esp.
17851cb0ef41Sopenharmony_ci    mov(scratch, esp);
17861cb0ef41Sopenharmony_ci    AllocateStackSpace((num_arguments + 1) * kSystemPointerSize);
17871cb0ef41Sopenharmony_ci    DCHECK(base::bits::IsPowerOfTwo(frame_alignment));
17881cb0ef41Sopenharmony_ci    and_(esp, -frame_alignment);
17891cb0ef41Sopenharmony_ci    mov(Operand(esp, num_arguments * kSystemPointerSize), scratch);
17901cb0ef41Sopenharmony_ci  } else {
17911cb0ef41Sopenharmony_ci    AllocateStackSpace(num_arguments * kSystemPointerSize);
17921cb0ef41Sopenharmony_ci  }
17931cb0ef41Sopenharmony_ci}
17941cb0ef41Sopenharmony_ci
17951cb0ef41Sopenharmony_civoid TurboAssembler::CallCFunction(ExternalReference function,
17961cb0ef41Sopenharmony_ci                                   int num_arguments) {
17971cb0ef41Sopenharmony_ci  // Trashing eax is ok as it will be the return value.
17981cb0ef41Sopenharmony_ci  Move(eax, Immediate(function));
17991cb0ef41Sopenharmony_ci  CallCFunction(eax, num_arguments);
18001cb0ef41Sopenharmony_ci}
18011cb0ef41Sopenharmony_ci
18021cb0ef41Sopenharmony_civoid TurboAssembler::CallCFunction(Register function, int num_arguments) {
18031cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
18041cb0ef41Sopenharmony_ci  DCHECK_LE(num_arguments, kMaxCParameters);
18051cb0ef41Sopenharmony_ci  DCHECK(has_frame());
18061cb0ef41Sopenharmony_ci  // Check stack alignment.
18071cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
18081cb0ef41Sopenharmony_ci    CheckStackAlignment();
18091cb0ef41Sopenharmony_ci  }
18101cb0ef41Sopenharmony_ci
18111cb0ef41Sopenharmony_ci  // Save the frame pointer and PC so that the stack layout remains iterable,
18121cb0ef41Sopenharmony_ci  // even without an ExitFrame which normally exists between JS and C frames.
18131cb0ef41Sopenharmony_ci  // Find two caller-saved scratch registers.
18141cb0ef41Sopenharmony_ci  Register pc_scratch = eax;
18151cb0ef41Sopenharmony_ci  Register scratch = ecx;
18161cb0ef41Sopenharmony_ci  if (function == eax) pc_scratch = edx;
18171cb0ef41Sopenharmony_ci  if (function == ecx) scratch = edx;
18181cb0ef41Sopenharmony_ci  PushPC();
18191cb0ef41Sopenharmony_ci  pop(pc_scratch);
18201cb0ef41Sopenharmony_ci
18211cb0ef41Sopenharmony_ci  // See x64 code for reasoning about how to address the isolate data fields.
18221cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(!root_array_available(), isolate() != nullptr);
18231cb0ef41Sopenharmony_ci  mov(root_array_available()
18241cb0ef41Sopenharmony_ci          ? Operand(kRootRegister, IsolateData::fast_c_call_caller_pc_offset())
18251cb0ef41Sopenharmony_ci          : ExternalReferenceAsOperand(
18261cb0ef41Sopenharmony_ci                ExternalReference::fast_c_call_caller_pc_address(isolate()),
18271cb0ef41Sopenharmony_ci                scratch),
18281cb0ef41Sopenharmony_ci      pc_scratch);
18291cb0ef41Sopenharmony_ci  mov(root_array_available()
18301cb0ef41Sopenharmony_ci          ? Operand(kRootRegister, IsolateData::fast_c_call_caller_fp_offset())
18311cb0ef41Sopenharmony_ci          : ExternalReferenceAsOperand(
18321cb0ef41Sopenharmony_ci                ExternalReference::fast_c_call_caller_fp_address(isolate()),
18331cb0ef41Sopenharmony_ci                scratch),
18341cb0ef41Sopenharmony_ci      ebp);
18351cb0ef41Sopenharmony_ci
18361cb0ef41Sopenharmony_ci  call(function);
18371cb0ef41Sopenharmony_ci
18381cb0ef41Sopenharmony_ci  // We don't unset the PC; the FP is the source of truth.
18391cb0ef41Sopenharmony_ci  mov(root_array_available()
18401cb0ef41Sopenharmony_ci          ? Operand(kRootRegister, IsolateData::fast_c_call_caller_fp_offset())
18411cb0ef41Sopenharmony_ci          : ExternalReferenceAsOperand(
18421cb0ef41Sopenharmony_ci                ExternalReference::fast_c_call_caller_fp_address(isolate()),
18431cb0ef41Sopenharmony_ci                scratch),
18441cb0ef41Sopenharmony_ci      Immediate(0));
18451cb0ef41Sopenharmony_ci
18461cb0ef41Sopenharmony_ci  if (base::OS::ActivationFrameAlignment() != 0) {
18471cb0ef41Sopenharmony_ci    mov(esp, Operand(esp, num_arguments * kSystemPointerSize));
18481cb0ef41Sopenharmony_ci  } else {
18491cb0ef41Sopenharmony_ci    add(esp, Immediate(num_arguments * kSystemPointerSize));
18501cb0ef41Sopenharmony_ci  }
18511cb0ef41Sopenharmony_ci}
18521cb0ef41Sopenharmony_ci
18531cb0ef41Sopenharmony_civoid TurboAssembler::PushPC() {
18541cb0ef41Sopenharmony_ci  // Push the current PC onto the stack as "return address" via calling
18551cb0ef41Sopenharmony_ci  // the next instruction.
18561cb0ef41Sopenharmony_ci  Label get_pc;
18571cb0ef41Sopenharmony_ci  call(&get_pc);
18581cb0ef41Sopenharmony_ci  bind(&get_pc);
18591cb0ef41Sopenharmony_ci}
18601cb0ef41Sopenharmony_ci
18611cb0ef41Sopenharmony_civoid TurboAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) {
18621cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
18631cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(options().isolate_independent_code,
18641cb0ef41Sopenharmony_ci                 Builtins::IsIsolateIndependentBuiltin(*code_object));
18651cb0ef41Sopenharmony_ci  if (options().inline_offheap_trampolines) {
18661cb0ef41Sopenharmony_ci    Builtin builtin = Builtin::kNoBuiltinId;
18671cb0ef41Sopenharmony_ci    if (isolate()->builtins()->IsBuiltinHandle(code_object, &builtin)) {
18681cb0ef41Sopenharmony_ci      // Inline the trampoline.
18691cb0ef41Sopenharmony_ci      CallBuiltin(builtin);
18701cb0ef41Sopenharmony_ci      return;
18711cb0ef41Sopenharmony_ci    }
18721cb0ef41Sopenharmony_ci  }
18731cb0ef41Sopenharmony_ci  DCHECK(RelocInfo::IsCodeTarget(rmode));
18741cb0ef41Sopenharmony_ci  call(code_object, rmode);
18751cb0ef41Sopenharmony_ci}
18761cb0ef41Sopenharmony_ci
18771cb0ef41Sopenharmony_civoid TurboAssembler::LoadEntryFromBuiltinIndex(Register builtin_index) {
18781cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
18791cb0ef41Sopenharmony_ci  STATIC_ASSERT(kSystemPointerSize == 4);
18801cb0ef41Sopenharmony_ci  STATIC_ASSERT(kSmiShiftSize == 0);
18811cb0ef41Sopenharmony_ci  STATIC_ASSERT(kSmiTagSize == 1);
18821cb0ef41Sopenharmony_ci  STATIC_ASSERT(kSmiTag == 0);
18831cb0ef41Sopenharmony_ci
18841cb0ef41Sopenharmony_ci  // The builtin_index register contains the builtin index as a Smi.
18851cb0ef41Sopenharmony_ci  // Untagging is folded into the indexing operand below (we use
18861cb0ef41Sopenharmony_ci  // times_half_system_pointer_size instead of times_system_pointer_size since
18871cb0ef41Sopenharmony_ci  // smis are already shifted by one).
18881cb0ef41Sopenharmony_ci  mov(builtin_index,
18891cb0ef41Sopenharmony_ci      Operand(kRootRegister, builtin_index, times_half_system_pointer_size,
18901cb0ef41Sopenharmony_ci              IsolateData::builtin_entry_table_offset()));
18911cb0ef41Sopenharmony_ci}
18921cb0ef41Sopenharmony_ci
18931cb0ef41Sopenharmony_civoid TurboAssembler::CallBuiltinByIndex(Register builtin_index) {
18941cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
18951cb0ef41Sopenharmony_ci  LoadEntryFromBuiltinIndex(builtin_index);
18961cb0ef41Sopenharmony_ci  call(builtin_index);
18971cb0ef41Sopenharmony_ci}
18981cb0ef41Sopenharmony_ci
18991cb0ef41Sopenharmony_civoid TurboAssembler::CallBuiltin(Builtin builtin) {
19001cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT_STRING(this, CommentForOffHeapTrampoline("call", builtin));
19011cb0ef41Sopenharmony_ci  DCHECK(Builtins::IsBuiltinId(builtin));
19021cb0ef41Sopenharmony_ci  call(BuiltinEntry(builtin), RelocInfo::OFF_HEAP_TARGET);
19031cb0ef41Sopenharmony_ci}
19041cb0ef41Sopenharmony_ci
19051cb0ef41Sopenharmony_ciOperand TurboAssembler::EntryFromBuiltinAsOperand(Builtin builtin) {
19061cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
19071cb0ef41Sopenharmony_ci  return Operand(kRootRegister, IsolateData::BuiltinEntrySlotOffset(builtin));
19081cb0ef41Sopenharmony_ci}
19091cb0ef41Sopenharmony_ci
19101cb0ef41Sopenharmony_civoid TurboAssembler::LoadCodeObjectEntry(Register destination,
19111cb0ef41Sopenharmony_ci                                         Register code_object) {
19121cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
19131cb0ef41Sopenharmony_ci  // Code objects are called differently depending on whether we are generating
19141cb0ef41Sopenharmony_ci  // builtin code (which will later be embedded into the binary) or compiling
19151cb0ef41Sopenharmony_ci  // user JS code at runtime.
19161cb0ef41Sopenharmony_ci  // * Builtin code runs in --jitless mode and thus must not call into on-heap
19171cb0ef41Sopenharmony_ci  //   Code targets. Instead, we dispatch through the builtins entry table.
19181cb0ef41Sopenharmony_ci  // * Codegen at runtime does not have this restriction and we can use the
19191cb0ef41Sopenharmony_ci  //   shorter, branchless instruction sequence. The assumption here is that
19201cb0ef41Sopenharmony_ci  //   targets are usually generated code and not builtin Code objects.
19211cb0ef41Sopenharmony_ci
19221cb0ef41Sopenharmony_ci  if (options().isolate_independent_code) {
19231cb0ef41Sopenharmony_ci    DCHECK(root_array_available());
19241cb0ef41Sopenharmony_ci    Label if_code_is_off_heap, out;
19251cb0ef41Sopenharmony_ci
19261cb0ef41Sopenharmony_ci    // Check whether the Code object is an off-heap trampoline. If so, call its
19271cb0ef41Sopenharmony_ci    // (off-heap) entry point directly without going through the (on-heap)
19281cb0ef41Sopenharmony_ci    // trampoline.  Otherwise, just call the Code object as always.
19291cb0ef41Sopenharmony_ci    test(FieldOperand(code_object, Code::kFlagsOffset),
19301cb0ef41Sopenharmony_ci         Immediate(Code::IsOffHeapTrampoline::kMask));
19311cb0ef41Sopenharmony_ci    j(not_equal, &if_code_is_off_heap);
19321cb0ef41Sopenharmony_ci
19331cb0ef41Sopenharmony_ci    // Not an off-heap trampoline, the entry point is at
19341cb0ef41Sopenharmony_ci    // Code::raw_instruction_start().
19351cb0ef41Sopenharmony_ci    Move(destination, code_object);
19361cb0ef41Sopenharmony_ci    add(destination, Immediate(Code::kHeaderSize - kHeapObjectTag));
19371cb0ef41Sopenharmony_ci    jmp(&out);
19381cb0ef41Sopenharmony_ci
19391cb0ef41Sopenharmony_ci    // An off-heap trampoline, the entry point is loaded from the builtin entry
19401cb0ef41Sopenharmony_ci    // table.
19411cb0ef41Sopenharmony_ci    bind(&if_code_is_off_heap);
19421cb0ef41Sopenharmony_ci    mov(destination, FieldOperand(code_object, Code::kBuiltinIndexOffset));
19431cb0ef41Sopenharmony_ci    mov(destination,
19441cb0ef41Sopenharmony_ci        Operand(kRootRegister, destination, times_system_pointer_size,
19451cb0ef41Sopenharmony_ci                IsolateData::builtin_entry_table_offset()));
19461cb0ef41Sopenharmony_ci
19471cb0ef41Sopenharmony_ci    bind(&out);
19481cb0ef41Sopenharmony_ci  } else {
19491cb0ef41Sopenharmony_ci    Move(destination, code_object);
19501cb0ef41Sopenharmony_ci    add(destination, Immediate(Code::kHeaderSize - kHeapObjectTag));
19511cb0ef41Sopenharmony_ci  }
19521cb0ef41Sopenharmony_ci}
19531cb0ef41Sopenharmony_ci
19541cb0ef41Sopenharmony_civoid TurboAssembler::CallCodeObject(Register code_object) {
19551cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
19561cb0ef41Sopenharmony_ci  LoadCodeObjectEntry(code_object, code_object);
19571cb0ef41Sopenharmony_ci  call(code_object);
19581cb0ef41Sopenharmony_ci}
19591cb0ef41Sopenharmony_ci
19601cb0ef41Sopenharmony_civoid TurboAssembler::JumpCodeObject(Register code_object, JumpMode jump_mode) {
19611cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
19621cb0ef41Sopenharmony_ci  LoadCodeObjectEntry(code_object, code_object);
19631cb0ef41Sopenharmony_ci  switch (jump_mode) {
19641cb0ef41Sopenharmony_ci    case JumpMode::kJump:
19651cb0ef41Sopenharmony_ci      jmp(code_object);
19661cb0ef41Sopenharmony_ci      return;
19671cb0ef41Sopenharmony_ci    case JumpMode::kPushAndReturn:
19681cb0ef41Sopenharmony_ci      push(code_object);
19691cb0ef41Sopenharmony_ci      ret(0);
19701cb0ef41Sopenharmony_ci      return;
19711cb0ef41Sopenharmony_ci  }
19721cb0ef41Sopenharmony_ci}
19731cb0ef41Sopenharmony_ci
19741cb0ef41Sopenharmony_civoid TurboAssembler::Jump(const ExternalReference& reference) {
19751cb0ef41Sopenharmony_ci  DCHECK(root_array_available());
19761cb0ef41Sopenharmony_ci  jmp(Operand(kRootRegister, RootRegisterOffsetForExternalReferenceTableEntry(
19771cb0ef41Sopenharmony_ci                                 isolate(), reference)));
19781cb0ef41Sopenharmony_ci}
19791cb0ef41Sopenharmony_ci
19801cb0ef41Sopenharmony_civoid TurboAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
19811cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(options().isolate_independent_code,
19821cb0ef41Sopenharmony_ci                 Builtins::IsIsolateIndependentBuiltin(*code_object));
19831cb0ef41Sopenharmony_ci  if (options().inline_offheap_trampolines) {
19841cb0ef41Sopenharmony_ci    Builtin builtin = Builtin::kNoBuiltinId;
19851cb0ef41Sopenharmony_ci    if (isolate()->builtins()->IsBuiltinHandle(code_object, &builtin)) {
19861cb0ef41Sopenharmony_ci      // Inline the trampoline.
19871cb0ef41Sopenharmony_ci      RecordCommentForOffHeapTrampoline(builtin);
19881cb0ef41Sopenharmony_ci      jmp(BuiltinEntry(builtin), RelocInfo::OFF_HEAP_TARGET);
19891cb0ef41Sopenharmony_ci      return;
19901cb0ef41Sopenharmony_ci    }
19911cb0ef41Sopenharmony_ci  }
19921cb0ef41Sopenharmony_ci  DCHECK(RelocInfo::IsCodeTarget(rmode));
19931cb0ef41Sopenharmony_ci  jmp(code_object, rmode);
19941cb0ef41Sopenharmony_ci}
19951cb0ef41Sopenharmony_ci
19961cb0ef41Sopenharmony_civoid TurboAssembler::CheckPageFlag(Register object, Register scratch, int mask,
19971cb0ef41Sopenharmony_ci                                   Condition cc, Label* condition_met,
19981cb0ef41Sopenharmony_ci                                   Label::Distance condition_met_distance) {
19991cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
20001cb0ef41Sopenharmony_ci  DCHECK(cc == zero || cc == not_zero);
20011cb0ef41Sopenharmony_ci  if (scratch == object) {
20021cb0ef41Sopenharmony_ci    and_(scratch, Immediate(~kPageAlignmentMask));
20031cb0ef41Sopenharmony_ci  } else {
20041cb0ef41Sopenharmony_ci    mov(scratch, Immediate(~kPageAlignmentMask));
20051cb0ef41Sopenharmony_ci    and_(scratch, object);
20061cb0ef41Sopenharmony_ci  }
20071cb0ef41Sopenharmony_ci  if (mask < (1 << kBitsPerByte)) {
20081cb0ef41Sopenharmony_ci    test_b(Operand(scratch, BasicMemoryChunk::kFlagsOffset), Immediate(mask));
20091cb0ef41Sopenharmony_ci  } else {
20101cb0ef41Sopenharmony_ci    test(Operand(scratch, BasicMemoryChunk::kFlagsOffset), Immediate(mask));
20111cb0ef41Sopenharmony_ci  }
20121cb0ef41Sopenharmony_ci  j(cc, condition_met, condition_met_distance);
20131cb0ef41Sopenharmony_ci}
20141cb0ef41Sopenharmony_ci
20151cb0ef41Sopenharmony_civoid TurboAssembler::ComputeCodeStartAddress(Register dst) {
20161cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
20171cb0ef41Sopenharmony_ci  // In order to get the address of the current instruction, we first need
20181cb0ef41Sopenharmony_ci  // to use a call and then use a pop, thus pushing the return address to
20191cb0ef41Sopenharmony_ci  // the stack and then popping it into the register.
20201cb0ef41Sopenharmony_ci  Label current;
20211cb0ef41Sopenharmony_ci  call(&current);
20221cb0ef41Sopenharmony_ci  int pc = pc_offset();
20231cb0ef41Sopenharmony_ci  bind(&current);
20241cb0ef41Sopenharmony_ci  pop(dst);
20251cb0ef41Sopenharmony_ci  if (pc != 0) {
20261cb0ef41Sopenharmony_ci    sub(dst, Immediate(pc));
20271cb0ef41Sopenharmony_ci  }
20281cb0ef41Sopenharmony_ci}
20291cb0ef41Sopenharmony_ci
20301cb0ef41Sopenharmony_civoid TurboAssembler::CallForDeoptimization(Builtin target, int, Label* exit,
20311cb0ef41Sopenharmony_ci                                           DeoptimizeKind kind, Label* ret,
20321cb0ef41Sopenharmony_ci                                           Label*) {
20331cb0ef41Sopenharmony_ci  ASM_CODE_COMMENT(this);
20341cb0ef41Sopenharmony_ci  CallBuiltin(target);
20351cb0ef41Sopenharmony_ci  DCHECK_EQ(SizeOfCodeGeneratedSince(exit),
20361cb0ef41Sopenharmony_ci            (kind == DeoptimizeKind::kLazy) ? Deoptimizer::kLazyDeoptExitSize
20371cb0ef41Sopenharmony_ci                                            : Deoptimizer::kEagerDeoptExitSize);
20381cb0ef41Sopenharmony_ci}
20391cb0ef41Sopenharmony_ci
20401cb0ef41Sopenharmony_civoid TurboAssembler::Trap() { int3(); }
20411cb0ef41Sopenharmony_civoid TurboAssembler::DebugBreak() { int3(); }
20421cb0ef41Sopenharmony_ci
20431cb0ef41Sopenharmony_ci}  // namespace internal
20441cb0ef41Sopenharmony_ci}  // namespace v8
20451cb0ef41Sopenharmony_ci
20461cb0ef41Sopenharmony_ci#endif  // V8_TARGET_ARCH_IA32
2047