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