14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/compiler/trampoline/aarch64/common_call.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/compiler/assembler/assembler.h"
194514f5e3Sopenharmony_ci#include "ecmascript/compiler/argument_accessor.h"
204514f5e3Sopenharmony_ci#include "ecmascript/compiler/rt_call_signature.h"
214514f5e3Sopenharmony_ci#include "ecmascript/ecma_runtime_call_info.h"
224514f5e3Sopenharmony_ci#include "ecmascript/frames.h"
234514f5e3Sopenharmony_ci#include "ecmascript/js_function.h"
244514f5e3Sopenharmony_ci#include "ecmascript/mem/machine_code.h"
254514f5e3Sopenharmony_ci#include "ecmascript/method.h"
264514f5e3Sopenharmony_ci#include "ecmascript/js_thread.h"
274514f5e3Sopenharmony_ci#include "ecmascript/js_generator_object.h"
284514f5e3Sopenharmony_ci#include "ecmascript/message_string.h"
294514f5e3Sopenharmony_ci#include "ecmascript/runtime_call_id.h"
304514f5e3Sopenharmony_ci
314514f5e3Sopenharmony_cinamespace panda::ecmascript::aarch64 {
324514f5e3Sopenharmony_ciusing Label = panda::ecmascript::Label;
334514f5e3Sopenharmony_ci#define __ assembler->
344514f5e3Sopenharmony_ci
354514f5e3Sopenharmony_ci// Generate code for entering asm interpreter
364514f5e3Sopenharmony_ci// c++ calling convention
374514f5e3Sopenharmony_ci// Input: glue           - %X0
384514f5e3Sopenharmony_ci//        callTarget     - %X1
394514f5e3Sopenharmony_ci//        method         - %X2
404514f5e3Sopenharmony_ci//        callField      - %X3
414514f5e3Sopenharmony_ci//        argc           - %X4
424514f5e3Sopenharmony_ci//        argv           - %X5(<callTarget, newTarget, this> are at the beginning of argv)
434514f5e3Sopenharmony_civoid AsmInterpreterCall::AsmInterpreterEntry(ExtendedAssembler *assembler)
444514f5e3Sopenharmony_ci{
454514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(AsmInterpreterEntry));
464514f5e3Sopenharmony_ci    Label target;
474514f5e3Sopenharmony_ci    size_t begin = __ GetCurrentPosition();
484514f5e3Sopenharmony_ci    PushAsmInterpEntryFrame(assembler);
494514f5e3Sopenharmony_ci    __ Bl(&target);
504514f5e3Sopenharmony_ci    PopAsmInterpEntryFrame(assembler);
514514f5e3Sopenharmony_ci    size_t end = __ GetCurrentPosition();
524514f5e3Sopenharmony_ci    if ((end - begin) != FrameCompletionPos::ARM64EntryFrameDuration) {
534514f5e3Sopenharmony_ci        LOG_COMPILER(FATAL) << (end - begin) << " != " << FrameCompletionPos::ARM64EntryFrameDuration
544514f5e3Sopenharmony_ci                            << "This frame has been modified, and the offset EntryFrameDuration should be updated too.";
554514f5e3Sopenharmony_ci    }
564514f5e3Sopenharmony_ci    __ Ret();
574514f5e3Sopenharmony_ci
584514f5e3Sopenharmony_ci    __ Bind(&target);
594514f5e3Sopenharmony_ci    {
604514f5e3Sopenharmony_ci        AsmInterpEntryDispatch(assembler);
614514f5e3Sopenharmony_ci    }
624514f5e3Sopenharmony_ci}
634514f5e3Sopenharmony_ci
644514f5e3Sopenharmony_ci// Input: glue           - %X0
654514f5e3Sopenharmony_ci//        callTarget     - %X1
664514f5e3Sopenharmony_ci//        method         - %X2
674514f5e3Sopenharmony_ci//        callField      - %X3
684514f5e3Sopenharmony_ci//        argc           - %X4
694514f5e3Sopenharmony_ci//        argv           - %X5(<callTarget, newTarget, this> are at the beginning of argv)
704514f5e3Sopenharmony_civoid AsmInterpreterCall::AsmInterpEntryDispatch(ExtendedAssembler *assembler)
714514f5e3Sopenharmony_ci{
724514f5e3Sopenharmony_ci    Label notJSFunction;
734514f5e3Sopenharmony_ci    Label callNativeEntry;
744514f5e3Sopenharmony_ci    Label callJSFunctionEntry;
754514f5e3Sopenharmony_ci    Label notCallable;
764514f5e3Sopenharmony_ci    Register glueRegister(X0);
774514f5e3Sopenharmony_ci    Register argcRegister(X4, W);
784514f5e3Sopenharmony_ci    Register argvRegister(X5);
794514f5e3Sopenharmony_ci    Register callTargetRegister(X1);
804514f5e3Sopenharmony_ci    Register callFieldRegister(X3);
814514f5e3Sopenharmony_ci    Register bitFieldRegister(X16);
824514f5e3Sopenharmony_ci    Register tempRegister(X17); // can not be used to store any variable
834514f5e3Sopenharmony_ci    Register functionTypeRegister(X18, W);
844514f5e3Sopenharmony_ci    __ Ldr(tempRegister, MemoryOperand(callTargetRegister, TaggedObject::HCLASS_OFFSET));
854514f5e3Sopenharmony_ci    __ Ldr(bitFieldRegister, MemoryOperand(tempRegister, JSHClass::BIT_FIELD_OFFSET));
864514f5e3Sopenharmony_ci    __ And(functionTypeRegister, bitFieldRegister.W(), LogicalImmediate::Create(0xFF, RegWSize));
874514f5e3Sopenharmony_ci    __ Mov(tempRegister.W(), Immediate(static_cast<int64_t>(JSType::JS_FUNCTION_FIRST)));
884514f5e3Sopenharmony_ci    __ Cmp(functionTypeRegister, tempRegister.W());
894514f5e3Sopenharmony_ci    __ B(Condition::LO, &notJSFunction);
904514f5e3Sopenharmony_ci    __ Mov(tempRegister.W(), Immediate(static_cast<int64_t>(JSType::JS_FUNCTION_LAST)));
914514f5e3Sopenharmony_ci    __ Cmp(functionTypeRegister, tempRegister.W());
924514f5e3Sopenharmony_ci    __ B(Condition::LS, &callJSFunctionEntry);
934514f5e3Sopenharmony_ci    __ Bind(&notJSFunction);
944514f5e3Sopenharmony_ci    {
954514f5e3Sopenharmony_ci        __ Tst(bitFieldRegister,
964514f5e3Sopenharmony_ci            LogicalImmediate::Create(static_cast<int64_t>(1ULL << JSHClass::CallableBit::START_BIT), RegXSize));
974514f5e3Sopenharmony_ci        __ B(Condition::EQ, &notCallable);
984514f5e3Sopenharmony_ci        // fall through
994514f5e3Sopenharmony_ci    }
1004514f5e3Sopenharmony_ci    __ Bind(&callNativeEntry);
1014514f5e3Sopenharmony_ci    CallNativeEntry(assembler);
1024514f5e3Sopenharmony_ci    __ Bind(&callJSFunctionEntry);
1034514f5e3Sopenharmony_ci    {
1044514f5e3Sopenharmony_ci        __ Tbnz(callFieldRegister, MethodLiteral::IsNativeBit::START_BIT, &callNativeEntry);
1054514f5e3Sopenharmony_ci        // fast path
1064514f5e3Sopenharmony_ci        __ Add(argvRegister, argvRegister, Immediate(NUM_MANDATORY_JSFUNC_ARGS * JSTaggedValue::TaggedTypeSize()));
1074514f5e3Sopenharmony_ci        JSCallCommonEntry(assembler, JSCallMode::CALL_ENTRY, FrameTransitionType::OTHER_TO_BASELINE_CHECK);
1084514f5e3Sopenharmony_ci    }
1094514f5e3Sopenharmony_ci    __ Bind(&notCallable);
1104514f5e3Sopenharmony_ci    {
1114514f5e3Sopenharmony_ci        Register runtimeId(X11);
1124514f5e3Sopenharmony_ci        Register trampoline(X12);
1134514f5e3Sopenharmony_ci        __ Mov(runtimeId, Immediate(kungfu::RuntimeStubCSigns::ID_ThrowNotCallableException));
1144514f5e3Sopenharmony_ci        // 3 : 3 means *8
1154514f5e3Sopenharmony_ci        __ Add(trampoline, glueRegister, Operand(runtimeId, LSL, 3));
1164514f5e3Sopenharmony_ci        __ Ldr(trampoline, MemoryOperand(trampoline, JSThread::GlueData::GetRTStubEntriesOffset(false)));
1174514f5e3Sopenharmony_ci        __ Blr(trampoline);
1184514f5e3Sopenharmony_ci        __ Ret();
1194514f5e3Sopenharmony_ci    }
1204514f5e3Sopenharmony_ci}
1214514f5e3Sopenharmony_ci
1224514f5e3Sopenharmony_civoid AsmInterpreterCall::JSCallCommonEntry(ExtendedAssembler *assembler,
1234514f5e3Sopenharmony_ci    JSCallMode mode, FrameTransitionType type)
1244514f5e3Sopenharmony_ci{
1254514f5e3Sopenharmony_ci    Label stackOverflow;
1264514f5e3Sopenharmony_ci    Register glueRegister = __ GlueRegister();
1274514f5e3Sopenharmony_ci    Register fpRegister = __ AvailableRegister1();
1284514f5e3Sopenharmony_ci    Register currentSlotRegister = __ AvailableRegister3();
1294514f5e3Sopenharmony_ci    Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD);
1304514f5e3Sopenharmony_ci    Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC);
1314514f5e3Sopenharmony_ci    if (!kungfu::AssemblerModule::IsJumpToCallCommonEntry(mode) || type == FrameTransitionType::BASELINE_TO_OTHER ||
1324514f5e3Sopenharmony_ci        type == FrameTransitionType::BASELINE_TO_BASELINE_CHECK) {
1334514f5e3Sopenharmony_ci        __ PushFpAndLr();
1344514f5e3Sopenharmony_ci    }
1354514f5e3Sopenharmony_ci    // save fp
1364514f5e3Sopenharmony_ci    __ Mov(fpRegister, Register(SP));
1374514f5e3Sopenharmony_ci    __ Mov(currentSlotRegister, Register(SP));
1384514f5e3Sopenharmony_ci
1394514f5e3Sopenharmony_ci    {
1404514f5e3Sopenharmony_ci        // Reserve enough sp space to prevent stack parameters from being covered by cpu profiler.
1414514f5e3Sopenharmony_ci        [[maybe_unused]] TempRegister1Scope scope(assembler);
1424514f5e3Sopenharmony_ci        Register tempRegister = __ TempRegister1();
1434514f5e3Sopenharmony_ci        __ Ldr(tempRegister, MemoryOperand(glueRegister, JSThread::GlueData::GetStackLimitOffset(false)));
1444514f5e3Sopenharmony_ci        __ Mov(Register(SP), tempRegister);
1454514f5e3Sopenharmony_ci    }
1464514f5e3Sopenharmony_ci
1474514f5e3Sopenharmony_ci    Register declaredNumArgsRegister = __ AvailableRegister2();
1484514f5e3Sopenharmony_ci    GetDeclaredNumArgsFromCallField(assembler, callFieldRegister, declaredNumArgsRegister);
1494514f5e3Sopenharmony_ci
1504514f5e3Sopenharmony_ci    Label slowPathEntry;
1514514f5e3Sopenharmony_ci    Label fastPathEntry;
1524514f5e3Sopenharmony_ci    Label pushCallThis;
1534514f5e3Sopenharmony_ci    auto argc = kungfu::AssemblerModule::GetArgcFromJSCallMode(mode);
1544514f5e3Sopenharmony_ci    if (argc >= 0) {
1554514f5e3Sopenharmony_ci        __ Cmp(declaredNumArgsRegister, Immediate(argc));
1564514f5e3Sopenharmony_ci    } else {
1574514f5e3Sopenharmony_ci        __ Cmp(declaredNumArgsRegister, argcRegister);
1584514f5e3Sopenharmony_ci    }
1594514f5e3Sopenharmony_ci    __ B(Condition::NE, &slowPathEntry);
1604514f5e3Sopenharmony_ci    __ Bind(&fastPathEntry);
1614514f5e3Sopenharmony_ci    JSCallCommonFastPath(assembler, mode, &pushCallThis, &stackOverflow);
1624514f5e3Sopenharmony_ci    __ Bind(&pushCallThis);
1634514f5e3Sopenharmony_ci    PushCallThis(assembler, mode, &stackOverflow, type);
1644514f5e3Sopenharmony_ci    __ Bind(&slowPathEntry);
1654514f5e3Sopenharmony_ci    JSCallCommonSlowPath(assembler, mode, &fastPathEntry, &pushCallThis, &stackOverflow);
1664514f5e3Sopenharmony_ci
1674514f5e3Sopenharmony_ci    __ Bind(&stackOverflow);
1684514f5e3Sopenharmony_ci    if (kungfu::AssemblerModule::IsJumpToCallCommonEntry(mode)) {
1694514f5e3Sopenharmony_ci        __ Mov(Register(SP), fpRegister);
1704514f5e3Sopenharmony_ci        [[maybe_unused]] TempRegister1Scope scope(assembler);
1714514f5e3Sopenharmony_ci        Register temp = __ TempRegister1();
1724514f5e3Sopenharmony_ci        // only glue and acc are useful in exception handler
1734514f5e3Sopenharmony_ci        if (glueRegister.GetId() != X19) {
1744514f5e3Sopenharmony_ci            __ Mov(Register(X19), glueRegister);
1754514f5e3Sopenharmony_ci        }
1764514f5e3Sopenharmony_ci        Register acc(X23);
1774514f5e3Sopenharmony_ci        __ Mov(acc, Immediate(JSTaggedValue::VALUE_EXCEPTION));
1784514f5e3Sopenharmony_ci        Register methodRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::METHOD);
1794514f5e3Sopenharmony_ci        Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET);
1804514f5e3Sopenharmony_ci        // Reload pc to make sure stack trace is right
1814514f5e3Sopenharmony_ci        __ Mov(temp, callTargetRegister);
1824514f5e3Sopenharmony_ci        __ Ldr(Register(X20), MemoryOperand(methodRegister, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
1834514f5e3Sopenharmony_ci        // Reload constpool and profileInfo to make sure gc map work normally
1844514f5e3Sopenharmony_ci        __ Ldr(Register(X22), MemoryOperand(temp, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
1854514f5e3Sopenharmony_ci        __ Ldr(Register(X22), MemoryOperand(Register(X22), ProfileTypeInfoCell::VALUE_OFFSET));
1864514f5e3Sopenharmony_ci        __ Ldr(Register(X21), MemoryOperand(methodRegister, Method::CONSTANT_POOL_OFFSET));
1874514f5e3Sopenharmony_ci
1884514f5e3Sopenharmony_ci        __ Mov(temp, kungfu::BytecodeStubCSigns::ID_ThrowStackOverflowException);
1894514f5e3Sopenharmony_ci        __ Add(temp, glueRegister, Operand(temp, UXTW, 3));  // 3: bc * 8
1904514f5e3Sopenharmony_ci        __ Ldr(temp, MemoryOperand(temp, JSThread::GlueData::GetBCStubEntriesOffset(false)));
1914514f5e3Sopenharmony_ci        __ Br(temp);
1924514f5e3Sopenharmony_ci    } else {
1934514f5e3Sopenharmony_ci        [[maybe_unused]] TempRegister1Scope scope(assembler);
1944514f5e3Sopenharmony_ci        Register temp = __ TempRegister1();
1954514f5e3Sopenharmony_ci        ThrowStackOverflowExceptionAndReturn(assembler, glueRegister, fpRegister, temp);
1964514f5e3Sopenharmony_ci    }
1974514f5e3Sopenharmony_ci}
1984514f5e3Sopenharmony_ci
1994514f5e3Sopenharmony_civoid AsmInterpreterCall::JSCallCommonFastPath(ExtendedAssembler *assembler, JSCallMode mode, Label *pushCallThis,
2004514f5e3Sopenharmony_ci    Label *stackOverflow)
2014514f5e3Sopenharmony_ci{
2024514f5e3Sopenharmony_ci    Register glueRegister = __ GlueRegister();
2034514f5e3Sopenharmony_ci    auto argc = kungfu::AssemblerModule::GetArgcFromJSCallMode(mode);
2044514f5e3Sopenharmony_ci    Register currentSlotRegister = __ AvailableRegister3();
2054514f5e3Sopenharmony_ci    // call range
2064514f5e3Sopenharmony_ci    if (argc < 0) {
2074514f5e3Sopenharmony_ci        Register numRegister = __ AvailableRegister2();
2084514f5e3Sopenharmony_ci        Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC);
2094514f5e3Sopenharmony_ci        Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGV);
2104514f5e3Sopenharmony_ci        __ Mov(numRegister, argcRegister);
2114514f5e3Sopenharmony_ci        [[maybe_unused]] TempRegister1Scope scope(assembler);
2124514f5e3Sopenharmony_ci        Register opRegister = __ TempRegister1();
2134514f5e3Sopenharmony_ci        PushArgsWithArgv(assembler, glueRegister, numRegister, argvRegister, opRegister,
2144514f5e3Sopenharmony_ci                         currentSlotRegister, pushCallThis, stackOverflow);
2154514f5e3Sopenharmony_ci    } else if (argc > 0) {
2164514f5e3Sopenharmony_ci        if (argc > 2) { // 2: call arg2
2174514f5e3Sopenharmony_ci            Register arg2 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2);
2184514f5e3Sopenharmony_ci            __ Str(arg2, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
2194514f5e3Sopenharmony_ci        }
2204514f5e3Sopenharmony_ci        if (argc > 1) {
2214514f5e3Sopenharmony_ci            Register arg1 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
2224514f5e3Sopenharmony_ci            __ Str(arg1, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
2234514f5e3Sopenharmony_ci        }
2244514f5e3Sopenharmony_ci        if (argc > 0) {
2254514f5e3Sopenharmony_ci            Register arg0 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0);
2264514f5e3Sopenharmony_ci            __ Str(arg0, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
2274514f5e3Sopenharmony_ci        }
2284514f5e3Sopenharmony_ci    }
2294514f5e3Sopenharmony_ci}
2304514f5e3Sopenharmony_ci
2314514f5e3Sopenharmony_civoid AsmInterpreterCall::JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode,
2324514f5e3Sopenharmony_ci                                              Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow)
2334514f5e3Sopenharmony_ci{
2344514f5e3Sopenharmony_ci    Register glueRegister = __ GlueRegister();
2354514f5e3Sopenharmony_ci    Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD);
2364514f5e3Sopenharmony_ci    Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC);
2374514f5e3Sopenharmony_ci    Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGV);
2384514f5e3Sopenharmony_ci    Register currentSlotRegister = __ AvailableRegister3();
2394514f5e3Sopenharmony_ci    Register arg0 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0);
2404514f5e3Sopenharmony_ci    Register arg1 = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
2414514f5e3Sopenharmony_ci    Label noExtraEntry;
2424514f5e3Sopenharmony_ci    Label pushArgsEntry;
2434514f5e3Sopenharmony_ci
2444514f5e3Sopenharmony_ci    auto argc = kungfu::AssemblerModule::GetArgcFromJSCallMode(mode);
2454514f5e3Sopenharmony_ci    Register declaredNumArgsRegister = __ AvailableRegister2();
2464514f5e3Sopenharmony_ci    __ Tbz(callFieldRegister, MethodLiteral::HaveExtraBit::START_BIT, &noExtraEntry);
2474514f5e3Sopenharmony_ci    // extra entry
2484514f5e3Sopenharmony_ci    {
2494514f5e3Sopenharmony_ci        [[maybe_unused]] TempRegister1Scope scope1(assembler);
2504514f5e3Sopenharmony_ci        Register tempArgcRegister = __ TempRegister1();
2514514f5e3Sopenharmony_ci        if (argc >= 0) {
2524514f5e3Sopenharmony_ci            __ PushArgc(argc, tempArgcRegister, currentSlotRegister);
2534514f5e3Sopenharmony_ci        } else {
2544514f5e3Sopenharmony_ci            __ PushArgc(argcRegister, tempArgcRegister, currentSlotRegister);
2554514f5e3Sopenharmony_ci        }
2564514f5e3Sopenharmony_ci        // fall through
2574514f5e3Sopenharmony_ci    }
2584514f5e3Sopenharmony_ci    __ Bind(&noExtraEntry);
2594514f5e3Sopenharmony_ci    {
2604514f5e3Sopenharmony_ci        if (argc == 0) {
2614514f5e3Sopenharmony_ci            {
2624514f5e3Sopenharmony_ci                [[maybe_unused]] TempRegister1Scope scope(assembler);
2634514f5e3Sopenharmony_ci                Register tempRegister = __ TempRegister1();
2644514f5e3Sopenharmony_ci                PushUndefinedWithArgc(assembler, glueRegister, declaredNumArgsRegister, tempRegister,
2654514f5e3Sopenharmony_ci                                      currentSlotRegister, nullptr, stackOverflow);
2664514f5e3Sopenharmony_ci            }
2674514f5e3Sopenharmony_ci            __ B(fastPathEntry);
2684514f5e3Sopenharmony_ci            return;
2694514f5e3Sopenharmony_ci        }
2704514f5e3Sopenharmony_ci        [[maybe_unused]] TempRegister1Scope scope1(assembler);
2714514f5e3Sopenharmony_ci        Register diffRegister = __ TempRegister1();
2724514f5e3Sopenharmony_ci        if (argc >= 0) {
2734514f5e3Sopenharmony_ci            __ Sub(diffRegister.W(), declaredNumArgsRegister.W(), Immediate(argc));
2744514f5e3Sopenharmony_ci        } else {
2754514f5e3Sopenharmony_ci            __ Sub(diffRegister.W(), declaredNumArgsRegister.W(), argcRegister.W());
2764514f5e3Sopenharmony_ci        }
2774514f5e3Sopenharmony_ci        [[maybe_unused]] TempRegister2Scope scope2(assembler);
2784514f5e3Sopenharmony_ci        Register tempRegister = __ TempRegister2();
2794514f5e3Sopenharmony_ci        PushUndefinedWithArgc(assembler, glueRegister, diffRegister, tempRegister,
2804514f5e3Sopenharmony_ci                              currentSlotRegister, &pushArgsEntry, stackOverflow);
2814514f5e3Sopenharmony_ci        __ B(fastPathEntry);
2824514f5e3Sopenharmony_ci    }
2834514f5e3Sopenharmony_ci    // declare < actual
2844514f5e3Sopenharmony_ci    __ Bind(&pushArgsEntry);
2854514f5e3Sopenharmony_ci    {
2864514f5e3Sopenharmony_ci        __ Tbnz(callFieldRegister, MethodLiteral::HaveExtraBit::START_BIT, fastPathEntry);
2874514f5e3Sopenharmony_ci        // no extra branch
2884514f5e3Sopenharmony_ci        // arg1, declare must be 0
2894514f5e3Sopenharmony_ci        if (argc == 1) {
2904514f5e3Sopenharmony_ci            __ B(pushCallThis);
2914514f5e3Sopenharmony_ci            return;
2924514f5e3Sopenharmony_ci        }
2934514f5e3Sopenharmony_ci        __ Cmp(declaredNumArgsRegister, Immediate(0));
2944514f5e3Sopenharmony_ci        __ B(Condition::EQ, pushCallThis);
2954514f5e3Sopenharmony_ci        // call range
2964514f5e3Sopenharmony_ci        if (argc < 0) {
2974514f5e3Sopenharmony_ci            [[maybe_unused]] TempRegister1Scope scope(assembler);
2984514f5e3Sopenharmony_ci            Register opRegister = __ TempRegister1();
2994514f5e3Sopenharmony_ci            PushArgsWithArgv(assembler, glueRegister, declaredNumArgsRegister,
3004514f5e3Sopenharmony_ci                             argvRegister, opRegister,
3014514f5e3Sopenharmony_ci                             currentSlotRegister, nullptr, stackOverflow);
3024514f5e3Sopenharmony_ci        } else if (argc > 0) {
3034514f5e3Sopenharmony_ci            Label pushArgs0;
3044514f5e3Sopenharmony_ci            if (argc > 2) {  // 2: call arg2
3054514f5e3Sopenharmony_ci                // decalare is 2 or 1 now
3064514f5e3Sopenharmony_ci                __ Cmp(declaredNumArgsRegister, Immediate(1));
3074514f5e3Sopenharmony_ci                __ B(Condition::EQ, &pushArgs0);
3084514f5e3Sopenharmony_ci                __ Str(arg1, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
3094514f5e3Sopenharmony_ci            }
3104514f5e3Sopenharmony_ci            if (argc > 1) {
3114514f5e3Sopenharmony_ci                __ Bind(&pushArgs0);
3124514f5e3Sopenharmony_ci                // decalare is is 1 now
3134514f5e3Sopenharmony_ci                __ Str(arg0, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
3144514f5e3Sopenharmony_ci            }
3154514f5e3Sopenharmony_ci        }
3164514f5e3Sopenharmony_ci        __ B(pushCallThis);
3174514f5e3Sopenharmony_ci    }
3184514f5e3Sopenharmony_ci}
3194514f5e3Sopenharmony_ci
3204514f5e3Sopenharmony_ciRegister AsmInterpreterCall::GetThisRegsiter(ExtendedAssembler *assembler, JSCallMode mode, Register defaultRegister)
3214514f5e3Sopenharmony_ci{
3224514f5e3Sopenharmony_ci    switch (mode) {
3234514f5e3Sopenharmony_ci        case JSCallMode::CALL_GETTER:
3244514f5e3Sopenharmony_ci        case JSCallMode::CALL_THIS_ARG0:
3254514f5e3Sopenharmony_ci            return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0);
3264514f5e3Sopenharmony_ci        case JSCallMode::CALL_SETTER:
3274514f5e3Sopenharmony_ci        case JSCallMode::CALL_THIS_ARG1:
3284514f5e3Sopenharmony_ci            return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
3294514f5e3Sopenharmony_ci        case JSCallMode::CALL_THIS_ARG2:
3304514f5e3Sopenharmony_ci        case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
3314514f5e3Sopenharmony_ci        case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
3324514f5e3Sopenharmony_ci        case JSCallMode::SUPER_CALL_WITH_ARGV:
3334514f5e3Sopenharmony_ci        case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
3344514f5e3Sopenharmony_ci        case JSCallMode::CALL_THIS_WITH_ARGV:
3354514f5e3Sopenharmony_ci        case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
3364514f5e3Sopenharmony_ci            return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2);
3374514f5e3Sopenharmony_ci        case JSCallMode::CALL_THIS_ARG3:
3384514f5e3Sopenharmony_ci        case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
3394514f5e3Sopenharmony_ci            return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG3);
3404514f5e3Sopenharmony_ci        case JSCallMode::CALL_FROM_AOT:
3414514f5e3Sopenharmony_ci        case JSCallMode::CALL_ENTRY: {
3424514f5e3Sopenharmony_ci            Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
3434514f5e3Sopenharmony_ci            __ Ldur(defaultRegister, MemoryOperand(argvRegister, -FRAME_SLOT_SIZE));
3444514f5e3Sopenharmony_ci            return defaultRegister;
3454514f5e3Sopenharmony_ci        }
3464514f5e3Sopenharmony_ci        default:
3474514f5e3Sopenharmony_ci            LOG_ECMA(FATAL) << "this branch is unreachable";
3484514f5e3Sopenharmony_ci            UNREACHABLE();
3494514f5e3Sopenharmony_ci    }
3504514f5e3Sopenharmony_ci    return INVALID_REG;
3514514f5e3Sopenharmony_ci}
3524514f5e3Sopenharmony_ci
3534514f5e3Sopenharmony_ciRegister AsmInterpreterCall::GetNewTargetRegsiter(ExtendedAssembler *assembler, JSCallMode mode,
3544514f5e3Sopenharmony_ci    Register defaultRegister)
3554514f5e3Sopenharmony_ci{
3564514f5e3Sopenharmony_ci    switch (mode) {
3574514f5e3Sopenharmony_ci        case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
3584514f5e3Sopenharmony_ci        case JSCallMode::CALL_THIS_WITH_ARGV:
3594514f5e3Sopenharmony_ci            return __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET);
3604514f5e3Sopenharmony_ci        case JSCallMode::SUPER_CALL_WITH_ARGV:
3614514f5e3Sopenharmony_ci        case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
3624514f5e3Sopenharmony_ci            return __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG3);
3634514f5e3Sopenharmony_ci        case JSCallMode::CALL_FROM_AOT:
3644514f5e3Sopenharmony_ci        case JSCallMode::CALL_ENTRY: {
3654514f5e3Sopenharmony_ci            Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
3664514f5e3Sopenharmony_ci            // 2: new Target index
3674514f5e3Sopenharmony_ci            __ Ldur(defaultRegister, MemoryOperand(argvRegister, -2 * FRAME_SLOT_SIZE));
3684514f5e3Sopenharmony_ci            return defaultRegister;
3694514f5e3Sopenharmony_ci        }
3704514f5e3Sopenharmony_ci        default:
3714514f5e3Sopenharmony_ci            LOG_ECMA(FATAL) << "this branch is unreachable";
3724514f5e3Sopenharmony_ci            UNREACHABLE();
3734514f5e3Sopenharmony_ci    }
3744514f5e3Sopenharmony_ci    return INVALID_REG;
3754514f5e3Sopenharmony_ci}
3764514f5e3Sopenharmony_ci
3774514f5e3Sopenharmony_ci// void PushCallArgsxAndDispatch(uintptr_t glue, uintptr_t sp, uint64_t callTarget, uintptr_t method,
3784514f5e3Sopenharmony_ci//     uint64_t callField, ...)
3794514f5e3Sopenharmony_ci// GHC calling convention
3804514f5e3Sopenharmony_ci// Input1: for callarg0/1/2/3        Input2: for callrange
3814514f5e3Sopenharmony_ci// X19 - glue                        // X19 - glue
3824514f5e3Sopenharmony_ci// FP  - sp                          // FP  - sp
3834514f5e3Sopenharmony_ci// X20 - callTarget                  // X20 - callTarget
3844514f5e3Sopenharmony_ci// X21 - method                      // X21 - method
3854514f5e3Sopenharmony_ci// X22 - callField                   // X22 - callField
3864514f5e3Sopenharmony_ci// X23 - arg0                        // X23 - actualArgc
3874514f5e3Sopenharmony_ci// X24 - arg1                        // X24 - argv
3884514f5e3Sopenharmony_ci// X25 - arg2
3894514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThisRangeAndDispatch(ExtendedAssembler *assembler)
3904514f5e3Sopenharmony_ci{
3914514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallThisRangeAndDispatch));
3924514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_WITH_ARGV, FrameTransitionType::OTHER_TO_OTHER);
3934514f5e3Sopenharmony_ci}
3944514f5e3Sopenharmony_ci
3954514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallRangeAndDispatch(ExtendedAssembler *assembler)
3964514f5e3Sopenharmony_ci{
3974514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallRangeAndDispatch));
3984514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::CALL_WITH_ARGV, FrameTransitionType::OTHER_TO_OTHER);
3994514f5e3Sopenharmony_ci}
4004514f5e3Sopenharmony_ci
4014514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallNewAndDispatch(ExtendedAssembler *assembler)
4024514f5e3Sopenharmony_ci{
4034514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallNewAndDispatch));
4044514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV, FrameTransitionType::OTHER_TO_OTHER);
4054514f5e3Sopenharmony_ci}
4064514f5e3Sopenharmony_ci
4074514f5e3Sopenharmony_civoid AsmInterpreterCall::PushSuperCallAndDispatch(ExtendedAssembler *assembler)
4084514f5e3Sopenharmony_ci{
4094514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushSuperCallAndDispatch));
4104514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::SUPER_CALL_WITH_ARGV, FrameTransitionType::OTHER_TO_OTHER);
4114514f5e3Sopenharmony_ci}
4124514f5e3Sopenharmony_ci
4134514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallArgs3AndDispatch(ExtendedAssembler *assembler)
4144514f5e3Sopenharmony_ci{
4154514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallArgs3AndDispatch));
4164514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::CALL_ARG3, FrameTransitionType::OTHER_TO_OTHER);
4174514f5e3Sopenharmony_ci}
4184514f5e3Sopenharmony_ci
4194514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallArgs2AndDispatch(ExtendedAssembler *assembler)
4204514f5e3Sopenharmony_ci{
4214514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallArgs2AndDispatch));
4224514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::CALL_ARG2, FrameTransitionType::OTHER_TO_OTHER);
4234514f5e3Sopenharmony_ci}
4244514f5e3Sopenharmony_ci
4254514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallArg1AndDispatch(ExtendedAssembler *assembler)
4264514f5e3Sopenharmony_ci{
4274514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallArg1AndDispatch));
4284514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::CALL_ARG1, FrameTransitionType::OTHER_TO_OTHER);
4294514f5e3Sopenharmony_ci}
4304514f5e3Sopenharmony_ci
4314514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallArg0AndDispatch(ExtendedAssembler *assembler)
4324514f5e3Sopenharmony_ci{
4334514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallArg0AndDispatch));
4344514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::CALL_ARG0, FrameTransitionType::OTHER_TO_OTHER);
4354514f5e3Sopenharmony_ci}
4364514f5e3Sopenharmony_ci
4374514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThisArg0AndDispatch(ExtendedAssembler *assembler)
4384514f5e3Sopenharmony_ci{
4394514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallThisArg0AndDispatch));
4404514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG0, FrameTransitionType::OTHER_TO_OTHER);
4414514f5e3Sopenharmony_ci}
4424514f5e3Sopenharmony_ci
4434514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThisArg1AndDispatch(ExtendedAssembler *assembler)
4444514f5e3Sopenharmony_ci{
4454514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallThisArg1AndDispatch));
4464514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG1, FrameTransitionType::OTHER_TO_OTHER);
4474514f5e3Sopenharmony_ci}
4484514f5e3Sopenharmony_ci
4494514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThisArgs2AndDispatch(ExtendedAssembler *assembler)
4504514f5e3Sopenharmony_ci{
4514514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallThisArgs2AndDispatch));
4524514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG2, FrameTransitionType::OTHER_TO_OTHER);
4534514f5e3Sopenharmony_ci}
4544514f5e3Sopenharmony_ci
4554514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThisArgs3AndDispatch(ExtendedAssembler *assembler)
4564514f5e3Sopenharmony_ci{
4574514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallThisArgs3AndDispatch));
4584514f5e3Sopenharmony_ci    JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG3, FrameTransitionType::OTHER_TO_OTHER);
4594514f5e3Sopenharmony_ci}
4604514f5e3Sopenharmony_ci
4614514f5e3Sopenharmony_ci// uint64_t PushCallRangeAndDispatchNative(uintptr_t glue, uint32_t argc, JSTaggedType calltarget, uintptr_t argv[])
4624514f5e3Sopenharmony_ci// c++ calling convention call js function
4634514f5e3Sopenharmony_ci// Input: X0 - glue
4644514f5e3Sopenharmony_ci//        X1 - nativeCode
4654514f5e3Sopenharmony_ci//        X2 - callTarget
4664514f5e3Sopenharmony_ci//        X3 - thisValue
4674514f5e3Sopenharmony_ci//        X4  - argc
4684514f5e3Sopenharmony_ci//        X5  - argV (...)
4694514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallRangeAndDispatchNative(ExtendedAssembler *assembler)
4704514f5e3Sopenharmony_ci{
4714514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallRangeAndDispatchNative));
4724514f5e3Sopenharmony_ci    CallNativeWithArgv(assembler, false);
4734514f5e3Sopenharmony_ci}
4744514f5e3Sopenharmony_ci
4754514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallNewAndDispatchNative(ExtendedAssembler *assembler)
4764514f5e3Sopenharmony_ci{
4774514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallNewAndDispatchNative));
4784514f5e3Sopenharmony_ci    CallNativeWithArgv(assembler, true);
4794514f5e3Sopenharmony_ci}
4804514f5e3Sopenharmony_ci
4814514f5e3Sopenharmony_civoid AsmInterpreterCall::PushNewTargetAndDispatchNative(ExtendedAssembler *assembler)
4824514f5e3Sopenharmony_ci{
4834514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushNewTargetAndDispatchNative));
4844514f5e3Sopenharmony_ci    CallNativeWithArgv(assembler, true, true);
4854514f5e3Sopenharmony_ci}
4864514f5e3Sopenharmony_ci
4874514f5e3Sopenharmony_civoid AsmInterpreterCall::CallNativeWithArgv(ExtendedAssembler *assembler, bool callNew, bool hasNewTarget)
4884514f5e3Sopenharmony_ci{
4894514f5e3Sopenharmony_ci    Register glue(X0);
4904514f5e3Sopenharmony_ci    Register nativeCode(X1);
4914514f5e3Sopenharmony_ci    Register callTarget(X2);
4924514f5e3Sopenharmony_ci    Register thisObj(X3);
4934514f5e3Sopenharmony_ci    Register argc(X4);
4944514f5e3Sopenharmony_ci    Register argv(X5);
4954514f5e3Sopenharmony_ci    Register newTarget(X6);
4964514f5e3Sopenharmony_ci    Register opArgc(X8);
4974514f5e3Sopenharmony_ci    Register opArgv(X9);
4984514f5e3Sopenharmony_ci    Register temp(X10);
4994514f5e3Sopenharmony_ci    Register currentSlotRegister(X11);
5004514f5e3Sopenharmony_ci    Register spRegister(SP);
5014514f5e3Sopenharmony_ci
5024514f5e3Sopenharmony_ci    Label pushThis;
5034514f5e3Sopenharmony_ci    Label stackOverflow;
5044514f5e3Sopenharmony_ci    bool isFrameComplete = PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_FRAME_WITH_ARGV, temp, argc);
5054514f5e3Sopenharmony_ci
5064514f5e3Sopenharmony_ci    __ Mov(currentSlotRegister, spRegister);
5074514f5e3Sopenharmony_ci    // Reserve enough sp space to prevent stack parameters from being covered by cpu profiler.
5084514f5e3Sopenharmony_ci    __ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetStackLimitOffset(false)));
5094514f5e3Sopenharmony_ci    __ Mov(Register(SP), temp);
5104514f5e3Sopenharmony_ci
5114514f5e3Sopenharmony_ci    __ Mov(opArgc, argc);
5124514f5e3Sopenharmony_ci    __ Mov(opArgv, argv);
5134514f5e3Sopenharmony_ci    PushArgsWithArgv(assembler, glue, opArgc, opArgv, temp, currentSlotRegister, &pushThis, &stackOverflow);
5144514f5e3Sopenharmony_ci
5154514f5e3Sopenharmony_ci    __ Bind(&pushThis);
5164514f5e3Sopenharmony_ci    // newTarget
5174514f5e3Sopenharmony_ci    if (callNew) {
5184514f5e3Sopenharmony_ci        if (hasNewTarget) {
5194514f5e3Sopenharmony_ci            // 16: this & newTarget
5204514f5e3Sopenharmony_ci            __ Stp(newTarget, thisObj, MemoryOperand(currentSlotRegister, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
5214514f5e3Sopenharmony_ci        } else {
5224514f5e3Sopenharmony_ci            // 16: this & newTarget
5234514f5e3Sopenharmony_ci            __ Stp(callTarget, thisObj, MemoryOperand(currentSlotRegister, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
5244514f5e3Sopenharmony_ci        }
5254514f5e3Sopenharmony_ci    } else {
5264514f5e3Sopenharmony_ci        __ Mov(temp, Immediate(JSTaggedValue::VALUE_UNDEFINED));
5274514f5e3Sopenharmony_ci        // 16: this & newTarget
5284514f5e3Sopenharmony_ci        __ Stp(temp, thisObj, MemoryOperand(currentSlotRegister, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX));
5294514f5e3Sopenharmony_ci    }
5304514f5e3Sopenharmony_ci    // callTarget
5314514f5e3Sopenharmony_ci    __ Str(callTarget, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
5324514f5e3Sopenharmony_ci    __ Add(temp, currentSlotRegister, Immediate(QUINTUPLE_SLOT_SIZE));
5334514f5e3Sopenharmony_ci    if (!isFrameComplete) {
5344514f5e3Sopenharmony_ci        __ Add(Register(FP), temp, Operand(argc, LSL, 3));  // 3: argc * 8
5354514f5e3Sopenharmony_ci    }
5364514f5e3Sopenharmony_ci
5374514f5e3Sopenharmony_ci    __ Add(temp, argc, Immediate(NUM_MANDATORY_JSFUNC_ARGS));
5384514f5e3Sopenharmony_ci    // 2: thread & argc
5394514f5e3Sopenharmony_ci    __ Stp(glue, temp, MemoryOperand(currentSlotRegister, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
5404514f5e3Sopenharmony_ci    __ Add(Register(X0), currentSlotRegister, Immediate(0));
5414514f5e3Sopenharmony_ci
5424514f5e3Sopenharmony_ci    __ Align16(currentSlotRegister);
5434514f5e3Sopenharmony_ci    __ Mov(spRegister, currentSlotRegister);
5444514f5e3Sopenharmony_ci
5454514f5e3Sopenharmony_ci    CallNativeInternal(assembler, nativeCode);
5464514f5e3Sopenharmony_ci    __ Ret();
5474514f5e3Sopenharmony_ci
5484514f5e3Sopenharmony_ci    __ Bind(&stackOverflow);
5494514f5e3Sopenharmony_ci    {
5504514f5e3Sopenharmony_ci        // use builtin_with_argv_frame to mark gc map
5514514f5e3Sopenharmony_ci        Register frameType(X11);
5524514f5e3Sopenharmony_ci        __ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
5534514f5e3Sopenharmony_ci        __ Mov(spRegister, temp);
5544514f5e3Sopenharmony_ci        __ Mov(frameType, Immediate(static_cast<int32_t>(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME)));
5554514f5e3Sopenharmony_ci        // 2: frame type and argc
5564514f5e3Sopenharmony_ci        __ Stp(Register(Zero), frameType, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
5574514f5e3Sopenharmony_ci        __ Mov(temp, Immediate(JSTaggedValue::VALUE_UNDEFINED));
5584514f5e3Sopenharmony_ci        // 2: fill this&newtgt slots
5594514f5e3Sopenharmony_ci        __ Stp(temp, temp, MemoryOperand(spRegister, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
5604514f5e3Sopenharmony_ci        // 2: fill func&align slots
5614514f5e3Sopenharmony_ci        __ Stp(Register(Zero), temp, MemoryOperand(spRegister, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX));
5624514f5e3Sopenharmony_ci        __ Mov(temp, spRegister);
5634514f5e3Sopenharmony_ci        // 6:frame type, argc, this, newTarget, func and align
5644514f5e3Sopenharmony_ci        // +----------------------------------------------------------------+ <---- fp = sp + 6 * frame_slot_size
5654514f5e3Sopenharmony_ci        // |     FrameType =  BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME |
5664514f5e3Sopenharmony_ci        // +----------------------------------------------------------------+
5674514f5e3Sopenharmony_ci        // |                           argc = 0                             |
5684514f5e3Sopenharmony_ci        // |----------------------------------------------------------------|
5694514f5e3Sopenharmony_ci        // |                       this = undefined                         |
5704514f5e3Sopenharmony_ci        // |----------------------------------------------------------------|
5714514f5e3Sopenharmony_ci        // |                      newTarget = undefine                      |
5724514f5e3Sopenharmony_ci        // |----------------------------------------------------------------|
5734514f5e3Sopenharmony_ci        // |                       function = undefined                     |
5744514f5e3Sopenharmony_ci        // |----------------------------------------------------------------|
5754514f5e3Sopenharmony_ci        // |                               align                            |
5764514f5e3Sopenharmony_ci        // +----------------------------------------------------------------+  <---- sp
5774514f5e3Sopenharmony_ci        __ Add(Register(FP), temp, Immediate(FRAME_SLOT_SIZE * 6));
5784514f5e3Sopenharmony_ci
5794514f5e3Sopenharmony_ci        Register runtimeId(X11);
5804514f5e3Sopenharmony_ci        Register trampoline(X12);
5814514f5e3Sopenharmony_ci        __ Mov(runtimeId, Immediate(kungfu::RuntimeStubCSigns::ID_ThrowStackOverflowException));
5824514f5e3Sopenharmony_ci        // 3 : 3 means *8
5834514f5e3Sopenharmony_ci        __ Add(trampoline, glue, Operand(runtimeId, LSL, 3));
5844514f5e3Sopenharmony_ci        __ Ldr(trampoline, MemoryOperand(trampoline, JSThread::GlueData::GetRTStubEntriesOffset(false)));
5854514f5e3Sopenharmony_ci        __ Blr(trampoline);
5864514f5e3Sopenharmony_ci
5874514f5e3Sopenharmony_ci        // resume rsp
5884514f5e3Sopenharmony_ci        __ Mov(Register(SP), Register(FP));
5894514f5e3Sopenharmony_ci        __ RestoreFpAndLr();
5904514f5e3Sopenharmony_ci        __ Ret();
5914514f5e3Sopenharmony_ci    }
5924514f5e3Sopenharmony_ci}
5934514f5e3Sopenharmony_ci
5944514f5e3Sopenharmony_ci// uint64_t PushCallArgsAndDispatchNative(uintptr_t codeAddress, uintptr_t glue, uint32_t argc, ...)
5954514f5e3Sopenharmony_ci// webkit_jscc calling convention call runtime_id's runtion function(c-abi)
5964514f5e3Sopenharmony_ci// Input: X0 - codeAddress
5974514f5e3Sopenharmony_ci// stack layout: sp + N*8 argvN
5984514f5e3Sopenharmony_ci//               ........
5994514f5e3Sopenharmony_ci//               sp + 24: argv1
6004514f5e3Sopenharmony_ci//               sp + 16: argv0
6014514f5e3Sopenharmony_ci//               sp + 8:  actualArgc
6024514f5e3Sopenharmony_ci//               sp:      thread
6034514f5e3Sopenharmony_ci// construct Native Leave Frame
6044514f5e3Sopenharmony_ci//               +--------------------------+
6054514f5e3Sopenharmony_ci//               |     argV[N - 1]          |
6064514f5e3Sopenharmony_ci//               |--------------------------|
6074514f5e3Sopenharmony_ci//               |       . . . .            |
6084514f5e3Sopenharmony_ci//               |--------------------------+
6094514f5e3Sopenharmony_ci//               |     argV[2]=this         |
6104514f5e3Sopenharmony_ci//               +--------------------------+
6114514f5e3Sopenharmony_ci//               |     argV[1]=new-target   |
6124514f5e3Sopenharmony_ci//               +--------------------------+
6134514f5e3Sopenharmony_ci//               |     argV[0]=call-target  |
6144514f5e3Sopenharmony_ci//               +--------------------------+ ---------
6154514f5e3Sopenharmony_ci//               |       argc               |         ^
6164514f5e3Sopenharmony_ci//               |--------------------------|         |
6174514f5e3Sopenharmony_ci//               |       thread             |         |
6184514f5e3Sopenharmony_ci//               |--------------------------|         |
6194514f5e3Sopenharmony_ci//               |       returnAddr         |     BuiltinFrame
6204514f5e3Sopenharmony_ci//               |--------------------------|         |
6214514f5e3Sopenharmony_ci//               |       callsiteFp         |         |
6224514f5e3Sopenharmony_ci//               |--------------------------|         |
6234514f5e3Sopenharmony_ci//               |       frameType          |         v
6244514f5e3Sopenharmony_ci//               +--------------------------+ ---------
6254514f5e3Sopenharmony_ci
6264514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallArgsAndDispatchNative(ExtendedAssembler *assembler)
6274514f5e3Sopenharmony_ci{
6284514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(PushCallArgsAndDispatchNative));
6294514f5e3Sopenharmony_ci
6304514f5e3Sopenharmony_ci    Register nativeCode(X0);
6314514f5e3Sopenharmony_ci    Register glue(X1);
6324514f5e3Sopenharmony_ci    Register argv(X5);
6334514f5e3Sopenharmony_ci    Register temp(X6);
6344514f5e3Sopenharmony_ci    Register sp(SP);
6354514f5e3Sopenharmony_ci    Register nativeCodeTemp(X2);
6364514f5e3Sopenharmony_ci
6374514f5e3Sopenharmony_ci    __ Mov(nativeCodeTemp, nativeCode);
6384514f5e3Sopenharmony_ci
6394514f5e3Sopenharmony_ci    __ Ldr(glue, MemoryOperand(sp, 0));
6404514f5e3Sopenharmony_ci    __ Add(Register(X0), sp, Immediate(0));
6414514f5e3Sopenharmony_ci    PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_FRAME, temp, argv);
6424514f5e3Sopenharmony_ci
6434514f5e3Sopenharmony_ci    CallNativeInternal(assembler, nativeCodeTemp);
6444514f5e3Sopenharmony_ci    __ Ret();
6454514f5e3Sopenharmony_ci}
6464514f5e3Sopenharmony_ci
6474514f5e3Sopenharmony_cibool AsmInterpreterCall::PushBuiltinFrame(ExtendedAssembler *assembler, Register glue,
6484514f5e3Sopenharmony_ci    FrameType type, Register op, Register next)
6494514f5e3Sopenharmony_ci{
6504514f5e3Sopenharmony_ci    Register sp(SP);
6514514f5e3Sopenharmony_ci    __ PushFpAndLr();
6524514f5e3Sopenharmony_ci    __ Mov(op, sp);
6534514f5e3Sopenharmony_ci    __ Str(op, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
6544514f5e3Sopenharmony_ci    __ Mov(op, Immediate(static_cast<int32_t>(type)));
6554514f5e3Sopenharmony_ci    if (type == FrameType::BUILTIN_FRAME) {
6564514f5e3Sopenharmony_ci        // push stack args
6574514f5e3Sopenharmony_ci        __ Add(next, sp, Immediate(BuiltinFrame::GetStackArgsToFpDelta(false)));
6584514f5e3Sopenharmony_ci        // 2: -2 * FRAME_SLOT_SIZE means type & next
6594514f5e3Sopenharmony_ci        __ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
6604514f5e3Sopenharmony_ci        // 2: 2 * FRAME_SLOT_SIZE means skip next and frame type
6614514f5e3Sopenharmony_ci        __ Add(Register(FP), sp, Immediate(2 * FRAME_SLOT_SIZE));
6624514f5e3Sopenharmony_ci        return true;
6634514f5e3Sopenharmony_ci    } else if (type == FrameType::BUILTIN_ENTRY_FRAME) {
6644514f5e3Sopenharmony_ci        // 2: -2 * FRAME_SLOT_SIZE means type & next
6654514f5e3Sopenharmony_ci        __ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
6664514f5e3Sopenharmony_ci        // 2: 2 * FRAME_SLOT_SIZE means skip next and frame type
6674514f5e3Sopenharmony_ci        __ Add(Register(FP), sp, Immediate(2 * FRAME_SLOT_SIZE));
6684514f5e3Sopenharmony_ci        return true;
6694514f5e3Sopenharmony_ci    } else if (type == FrameType::BUILTIN_FRAME_WITH_ARGV) {
6704514f5e3Sopenharmony_ci        // this frame push stack args must before update FP, otherwise cpu profiler maybe visit incomplete stack
6714514f5e3Sopenharmony_ci        // BuiltinWithArgvFrame layout please see frames.h
6724514f5e3Sopenharmony_ci        // 2: -2 * FRAME_SLOT_SIZE means type & next
6734514f5e3Sopenharmony_ci        __ Stp(next, op, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
6744514f5e3Sopenharmony_ci        return false;
6754514f5e3Sopenharmony_ci    } else {
6764514f5e3Sopenharmony_ci        LOG_ECMA(FATAL) << "this branch is unreachable";
6774514f5e3Sopenharmony_ci        UNREACHABLE();
6784514f5e3Sopenharmony_ci    }
6794514f5e3Sopenharmony_ci}
6804514f5e3Sopenharmony_ci
6814514f5e3Sopenharmony_civoid AsmInterpreterCall::CallNativeInternal(ExtendedAssembler *assembler, Register nativeCode)
6824514f5e3Sopenharmony_ci{
6834514f5e3Sopenharmony_ci    __ Blr(nativeCode);
6844514f5e3Sopenharmony_ci    // resume rsp
6854514f5e3Sopenharmony_ci    __ Mov(Register(SP), Register(FP));
6864514f5e3Sopenharmony_ci    __ RestoreFpAndLr();
6874514f5e3Sopenharmony_ci}
6884514f5e3Sopenharmony_ci
6894514f5e3Sopenharmony_ci// ResumeRspAndDispatch(uintptr_t glue, uintptr_t sp, uintptr_t pc, uintptr_t constantPool,
6904514f5e3Sopenharmony_ci//     uint64_t profileTypeInfo, uint64_t acc, uint32_t hotnessCounter, size_t jumpSize)
6914514f5e3Sopenharmony_ci// GHC calling convention
6924514f5e3Sopenharmony_ci// X19 - glue
6934514f5e3Sopenharmony_ci// FP  - sp
6944514f5e3Sopenharmony_ci// X20 - pc
6954514f5e3Sopenharmony_ci// X21 - constantPool
6964514f5e3Sopenharmony_ci// X22 - profileTypeInfo
6974514f5e3Sopenharmony_ci// X23 - acc
6984514f5e3Sopenharmony_ci// X24 - hotnessCounter
6994514f5e3Sopenharmony_ci// X25 - jumpSizeAfterCall
7004514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeRspAndDispatch(ExtendedAssembler *assembler)
7014514f5e3Sopenharmony_ci{
7024514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndDispatch));
7034514f5e3Sopenharmony_ci
7044514f5e3Sopenharmony_ci    Register glueRegister = __ GlueRegister();
7054514f5e3Sopenharmony_ci    Register sp(FP);
7064514f5e3Sopenharmony_ci    Register rsp(SP);
7074514f5e3Sopenharmony_ci    Register pc(X20);
7084514f5e3Sopenharmony_ci    Register jumpSizeRegister(X25);
7094514f5e3Sopenharmony_ci
7104514f5e3Sopenharmony_ci    Register ret(X23);
7114514f5e3Sopenharmony_ci    Register opcode(X6, W);
7124514f5e3Sopenharmony_ci    Register temp(X7);
7134514f5e3Sopenharmony_ci    Register bcStub(X7);
7144514f5e3Sopenharmony_ci    Register fp(X8);
7154514f5e3Sopenharmony_ci
7164514f5e3Sopenharmony_ci    int64_t fpOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFpOffset(false))
7174514f5e3Sopenharmony_ci        - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false));
7184514f5e3Sopenharmony_ci    int64_t spOffset = static_cast<int64_t>(AsmInterpretedFrame::GetBaseOffset(false))
7194514f5e3Sopenharmony_ci        - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false));
7204514f5e3Sopenharmony_ci    int64_t thisOffset = static_cast<int64_t>(AsmInterpretedFrame::GetThisOffset(false))
7214514f5e3Sopenharmony_ci        - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false));
7224514f5e3Sopenharmony_ci    ASSERT(fpOffset < 0);
7234514f5e3Sopenharmony_ci    ASSERT(spOffset < 0);
7244514f5e3Sopenharmony_ci
7254514f5e3Sopenharmony_ci    Label newObjectRangeReturn;
7264514f5e3Sopenharmony_ci    Label dispatch;
7274514f5e3Sopenharmony_ci    __ Ldur(fp, MemoryOperand(sp, fpOffset));  // store fp for temporary
7284514f5e3Sopenharmony_ci    __ Cmp(jumpSizeRegister, Immediate(0));
7294514f5e3Sopenharmony_ci    __ B(Condition::LE, &newObjectRangeReturn);
7304514f5e3Sopenharmony_ci    __ Ldur(sp, MemoryOperand(sp, spOffset));  // update sp
7314514f5e3Sopenharmony_ci
7324514f5e3Sopenharmony_ci    __ Add(pc, pc, Operand(jumpSizeRegister, LSL, 0));
7334514f5e3Sopenharmony_ci    __ Ldrb(opcode, MemoryOperand(pc, 0));
7344514f5e3Sopenharmony_ci    __ Bind(&dispatch);
7354514f5e3Sopenharmony_ci    {
7364514f5e3Sopenharmony_ci        __ Mov(rsp, fp);  // resume rsp
7374514f5e3Sopenharmony_ci        __ Add(bcStub, glueRegister, Operand(opcode, UXTW, FRAME_SLOT_SIZE_LOG2));
7384514f5e3Sopenharmony_ci        __ Ldr(bcStub, MemoryOperand(bcStub, JSThread::GlueData::GetBCStubEntriesOffset(false)));
7394514f5e3Sopenharmony_ci        __ Br(bcStub);
7404514f5e3Sopenharmony_ci    }
7414514f5e3Sopenharmony_ci
7424514f5e3Sopenharmony_ci    Label getThis;
7434514f5e3Sopenharmony_ci    Label notUndefined;
7444514f5e3Sopenharmony_ci    __ Bind(&newObjectRangeReturn);
7454514f5e3Sopenharmony_ci    {
7464514f5e3Sopenharmony_ci        __ Cmp(ret, Immediate(JSTaggedValue::VALUE_UNDEFINED));
7474514f5e3Sopenharmony_ci        __ B(Condition::NE, &notUndefined);
7484514f5e3Sopenharmony_ci        ASSERT(thisOffset < 0);
7494514f5e3Sopenharmony_ci        __ Bind(&getThis);
7504514f5e3Sopenharmony_ci        __ Ldur(ret, MemoryOperand(sp, thisOffset));  // update acc
7514514f5e3Sopenharmony_ci        __ Ldur(sp, MemoryOperand(sp, spOffset));  // update sp
7524514f5e3Sopenharmony_ci        __ Mov(rsp, fp);  // resume rsp
7534514f5e3Sopenharmony_ci        __ Sub(pc, pc, jumpSizeRegister); // sub negative jmupSize
7544514f5e3Sopenharmony_ci        __ Ldrb(opcode, MemoryOperand(pc, 0));
7554514f5e3Sopenharmony_ci        __ Add(bcStub, glueRegister, Operand(opcode, UXTW, FRAME_SLOT_SIZE_LOG2));
7564514f5e3Sopenharmony_ci        __ Ldr(bcStub, MemoryOperand(bcStub, JSThread::GlueData::GetBCStubEntriesOffset(false)));
7574514f5e3Sopenharmony_ci        __ Br(bcStub);
7584514f5e3Sopenharmony_ci    }
7594514f5e3Sopenharmony_ci    __ Bind(&notUndefined);
7604514f5e3Sopenharmony_ci    {
7614514f5e3Sopenharmony_ci        Label notEcmaObject;
7624514f5e3Sopenharmony_ci        __ Mov(temp, Immediate(JSTaggedValue::TAG_HEAPOBJECT_MASK));
7634514f5e3Sopenharmony_ci        __ And(temp, temp, ret);
7644514f5e3Sopenharmony_ci        __ Cmp(temp, Immediate(0));
7654514f5e3Sopenharmony_ci        __ B(Condition::NE, &notEcmaObject);
7664514f5e3Sopenharmony_ci        // acc is heap object
7674514f5e3Sopenharmony_ci        __ Ldr(temp, MemoryOperand(ret, TaggedObject::HCLASS_OFFSET));
7684514f5e3Sopenharmony_ci        __ Ldr(temp, MemoryOperand(temp, JSHClass::BIT_FIELD_OFFSET));
7694514f5e3Sopenharmony_ci        __ And(temp.W(), temp.W(), LogicalImmediate::Create(0xFF, RegWSize));
7704514f5e3Sopenharmony_ci        __ Cmp(temp.W(), Immediate(static_cast<int64_t>(JSType::ECMA_OBJECT_LAST)));
7714514f5e3Sopenharmony_ci        __ B(Condition::HI, &notEcmaObject);
7724514f5e3Sopenharmony_ci        __ Cmp(temp.W(), Immediate(static_cast<int64_t>(JSType::ECMA_OBJECT_FIRST)));
7734514f5e3Sopenharmony_ci        __ B(Condition::LO, &notEcmaObject);
7744514f5e3Sopenharmony_ci        // acc is ecma object
7754514f5e3Sopenharmony_ci        __ Ldur(sp, MemoryOperand(sp, spOffset));  // update sp
7764514f5e3Sopenharmony_ci        __ Sub(pc, pc, jumpSizeRegister); // sub negative jmupSize
7774514f5e3Sopenharmony_ci        __ Ldrb(opcode, MemoryOperand(pc, 0));
7784514f5e3Sopenharmony_ci        __ B(&dispatch);
7794514f5e3Sopenharmony_ci
7804514f5e3Sopenharmony_ci        __ Bind(&notEcmaObject);
7814514f5e3Sopenharmony_ci        {
7824514f5e3Sopenharmony_ci            int64_t constructorOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFunctionOffset(false))
7834514f5e3Sopenharmony_ci                - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false));
7844514f5e3Sopenharmony_ci            ASSERT(constructorOffset < 0);
7854514f5e3Sopenharmony_ci            __ Ldur(temp, MemoryOperand(sp, constructorOffset));  // load constructor
7864514f5e3Sopenharmony_ci            __ Ldr(temp, MemoryOperand(temp, JSFunctionBase::METHOD_OFFSET));
7874514f5e3Sopenharmony_ci            __ Ldr(temp, MemoryOperand(temp, Method::EXTRA_LITERAL_INFO_OFFSET));
7884514f5e3Sopenharmony_ci            __ Lsr(temp.W(), temp.W(), MethodLiteral::FunctionKindBits::START_BIT);
7894514f5e3Sopenharmony_ci            __ And(temp.W(), temp.W(),
7904514f5e3Sopenharmony_ci                LogicalImmediate::Create((1LU << MethodLiteral::FunctionKindBits::SIZE) - 1, RegWSize));
7914514f5e3Sopenharmony_ci            __ Cmp(temp.W(), Immediate(static_cast<int64_t>(FunctionKind::CLASS_CONSTRUCTOR)));
7924514f5e3Sopenharmony_ci            __ B(Condition::LS, &getThis);  // constructor is base
7934514f5e3Sopenharmony_ci            // exception branch
7944514f5e3Sopenharmony_ci            {
7954514f5e3Sopenharmony_ci                __ Mov(opcode, kungfu::BytecodeStubCSigns::ID_NewObjectRangeThrowException);
7964514f5e3Sopenharmony_ci                __ Ldur(sp, MemoryOperand(sp, spOffset));  // update sp
7974514f5e3Sopenharmony_ci                __ B(&dispatch);
7984514f5e3Sopenharmony_ci            }
7994514f5e3Sopenharmony_ci        }
8004514f5e3Sopenharmony_ci    }
8014514f5e3Sopenharmony_ci}
8024514f5e3Sopenharmony_ci
8034514f5e3Sopenharmony_ci// ResumeRspAndReturn(uintptr_t acc)
8044514f5e3Sopenharmony_ci// GHC calling convention
8054514f5e3Sopenharmony_ci// X19 - acc
8064514f5e3Sopenharmony_ci// FP - prevSp
8074514f5e3Sopenharmony_ci// X20 - sp
8084514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeRspAndReturn(ExtendedAssembler *assembler)
8094514f5e3Sopenharmony_ci{
8104514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndReturn));
8114514f5e3Sopenharmony_ci    Register rsp(SP);
8124514f5e3Sopenharmony_ci    Register currentSp(X20);
8134514f5e3Sopenharmony_ci
8144514f5e3Sopenharmony_ci    [[maybe_unused]] TempRegister1Scope scope1(assembler);
8154514f5e3Sopenharmony_ci    Register fpRegister = __ TempRegister1();
8164514f5e3Sopenharmony_ci    int64_t offset = static_cast<int64_t>(AsmInterpretedFrame::GetFpOffset(false))
8174514f5e3Sopenharmony_ci        - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false));
8184514f5e3Sopenharmony_ci    ASSERT(offset < 0);
8194514f5e3Sopenharmony_ci    __ Ldur(fpRegister, MemoryOperand(currentSp, offset));
8204514f5e3Sopenharmony_ci    __ Mov(rsp, fpRegister);
8214514f5e3Sopenharmony_ci
8224514f5e3Sopenharmony_ci    // return
8234514f5e3Sopenharmony_ci    {
8244514f5e3Sopenharmony_ci        __ RestoreFpAndLr();
8254514f5e3Sopenharmony_ci        __ Mov(Register(X0), Register(X19));
8264514f5e3Sopenharmony_ci        __ Ret();
8274514f5e3Sopenharmony_ci    }
8284514f5e3Sopenharmony_ci}
8294514f5e3Sopenharmony_ci
8304514f5e3Sopenharmony_ci// ResumeRspAndReturnBaseline(uintptr_t acc)
8314514f5e3Sopenharmony_ci// GHC calling convention
8324514f5e3Sopenharmony_ci// X19 - acc
8334514f5e3Sopenharmony_ci// FP - prevSp
8344514f5e3Sopenharmony_ci// X20 - sp
8354514f5e3Sopenharmony_ci// X21 - jumpSizeAfterCall
8364514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeRspAndReturnBaseline(ExtendedAssembler *assembler)
8374514f5e3Sopenharmony_ci{
8384514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndReturnBaseline));
8394514f5e3Sopenharmony_ci    Register rsp(SP);
8404514f5e3Sopenharmony_ci    Register currentSp(X20);
8414514f5e3Sopenharmony_ci
8424514f5e3Sopenharmony_ci    [[maybe_unused]] TempRegister1Scope scope1(assembler);
8434514f5e3Sopenharmony_ci    Register fpRegister = __ TempRegister1();
8444514f5e3Sopenharmony_ci    int64_t fpOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFpOffset(false)) -
8454514f5e3Sopenharmony_ci        static_cast<int64_t>(AsmInterpretedFrame::GetSize(false));
8464514f5e3Sopenharmony_ci    ASSERT(fpOffset < 0);
8474514f5e3Sopenharmony_ci    __ Ldur(fpRegister, MemoryOperand(currentSp, fpOffset));
8484514f5e3Sopenharmony_ci    __ Mov(rsp, fpRegister);
8494514f5e3Sopenharmony_ci    __ RestoreFpAndLr();
8504514f5e3Sopenharmony_ci    __ Mov(Register(X0), Register(X19));
8514514f5e3Sopenharmony_ci
8524514f5e3Sopenharmony_ci    // Check and set result
8534514f5e3Sopenharmony_ci    Register ret = X0;
8544514f5e3Sopenharmony_ci    Register jumpSizeRegister = X21;
8554514f5e3Sopenharmony_ci    Label getThis;
8564514f5e3Sopenharmony_ci    Label notUndefined;
8574514f5e3Sopenharmony_ci    Label normalReturn;
8584514f5e3Sopenharmony_ci    Label newObjectRangeReturn;
8594514f5e3Sopenharmony_ci    __ Cmp(jumpSizeRegister, Immediate(0));
8604514f5e3Sopenharmony_ci    __ B(Condition::GT, &normalReturn);
8614514f5e3Sopenharmony_ci
8624514f5e3Sopenharmony_ci    __ Bind(&newObjectRangeReturn);
8634514f5e3Sopenharmony_ci    {
8644514f5e3Sopenharmony_ci        __ Cmp(ret, Immediate(JSTaggedValue::VALUE_UNDEFINED));
8654514f5e3Sopenharmony_ci        __ B(Condition::NE, &notUndefined);
8664514f5e3Sopenharmony_ci
8674514f5e3Sopenharmony_ci        __ Bind(&getThis);
8684514f5e3Sopenharmony_ci        int64_t thisOffset = static_cast<int64_t>(AsmInterpretedFrame::GetThisOffset(false)) -
8694514f5e3Sopenharmony_ci            static_cast<int64_t>(AsmInterpretedFrame::GetSize(false));
8704514f5e3Sopenharmony_ci        ASSERT(thisOffset < 0);
8714514f5e3Sopenharmony_ci        __ Ldur(ret, MemoryOperand(currentSp, thisOffset));  // update result
8724514f5e3Sopenharmony_ci        __ B(&normalReturn);
8734514f5e3Sopenharmony_ci
8744514f5e3Sopenharmony_ci        __ Bind(&notUndefined);
8754514f5e3Sopenharmony_ci        {
8764514f5e3Sopenharmony_ci            Register temp = X19;
8774514f5e3Sopenharmony_ci            Label notEcmaObject;
8784514f5e3Sopenharmony_ci            __ Mov(temp, Immediate(JSTaggedValue::TAG_HEAPOBJECT_MASK));
8794514f5e3Sopenharmony_ci            __ And(temp, temp, ret);
8804514f5e3Sopenharmony_ci            __ Cmp(temp, Immediate(0));
8814514f5e3Sopenharmony_ci            __ B(Condition::NE, &notEcmaObject);
8824514f5e3Sopenharmony_ci            // acc is heap object
8834514f5e3Sopenharmony_ci            __ Ldr(temp, MemoryOperand(ret, TaggedObject::HCLASS_OFFSET));
8844514f5e3Sopenharmony_ci            __ Ldr(temp, MemoryOperand(temp, JSHClass::BIT_FIELD_OFFSET));
8854514f5e3Sopenharmony_ci            __ And(temp.W(), temp.W(), LogicalImmediate::Create(0xFF, RegWSize));
8864514f5e3Sopenharmony_ci            __ Cmp(temp.W(), Immediate(static_cast<int64_t>(JSType::ECMA_OBJECT_LAST)));
8874514f5e3Sopenharmony_ci            __ B(Condition::HI, &notEcmaObject);
8884514f5e3Sopenharmony_ci            __ Cmp(temp.W(), Immediate(static_cast<int64_t>(JSType::ECMA_OBJECT_FIRST)));
8894514f5e3Sopenharmony_ci            __ B(Condition::LO, &notEcmaObject);
8904514f5e3Sopenharmony_ci            // acc is ecma object
8914514f5e3Sopenharmony_ci            __ B(&normalReturn);
8924514f5e3Sopenharmony_ci
8934514f5e3Sopenharmony_ci            __ Bind(&notEcmaObject);
8944514f5e3Sopenharmony_ci            {
8954514f5e3Sopenharmony_ci                int64_t funcOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFunctionOffset(false)) -
8964514f5e3Sopenharmony_ci                    static_cast<int64_t>(AsmInterpretedFrame::GetSize(false));
8974514f5e3Sopenharmony_ci                ASSERT(funcOffset < 0);
8984514f5e3Sopenharmony_ci                __ Ldur(temp, MemoryOperand(currentSp, funcOffset));  // load constructor
8994514f5e3Sopenharmony_ci                __ Ldr(temp, MemoryOperand(temp, JSFunctionBase::METHOD_OFFSET));
9004514f5e3Sopenharmony_ci                __ Ldr(temp, MemoryOperand(temp, Method::EXTRA_LITERAL_INFO_OFFSET));
9014514f5e3Sopenharmony_ci                __ Lsr(temp.W(), temp.W(), MethodLiteral::FunctionKindBits::START_BIT);
9024514f5e3Sopenharmony_ci                __ And(temp.W(), temp.W(),
9034514f5e3Sopenharmony_ci                       LogicalImmediate::Create((1LU << MethodLiteral::FunctionKindBits::SIZE) - 1, RegWSize));
9044514f5e3Sopenharmony_ci                __ Cmp(temp.W(), Immediate(static_cast<int64_t>(FunctionKind::CLASS_CONSTRUCTOR)));
9054514f5e3Sopenharmony_ci                __ B(Condition::LS, &getThis);  // constructor is base
9064514f5e3Sopenharmony_ci                // fall through
9074514f5e3Sopenharmony_ci            }
9084514f5e3Sopenharmony_ci        }
9094514f5e3Sopenharmony_ci    }
9104514f5e3Sopenharmony_ci    __ Bind(&normalReturn);
9114514f5e3Sopenharmony_ci    __ Ret();
9124514f5e3Sopenharmony_ci}
9134514f5e3Sopenharmony_ci
9144514f5e3Sopenharmony_ci// ResumeCaughtFrameAndDispatch(uintptr_t glue, uintptr_t sp, uintptr_t pc, uintptr_t constantPool,
9154514f5e3Sopenharmony_ci//     uint64_t profileTypeInfo, uint64_t acc, uint32_t hotnessCounter)
9164514f5e3Sopenharmony_ci// GHC calling convention
9174514f5e3Sopenharmony_ci// X19 - glue
9184514f5e3Sopenharmony_ci// FP  - sp
9194514f5e3Sopenharmony_ci// X20 - pc
9204514f5e3Sopenharmony_ci// X21 - constantPool
9214514f5e3Sopenharmony_ci// X22 - profileTypeInfo
9224514f5e3Sopenharmony_ci// X23 - acc
9234514f5e3Sopenharmony_ci// X24 - hotnessCounter
9244514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler)
9254514f5e3Sopenharmony_ci{
9264514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(ResumeCaughtFrameAndDispatch));
9274514f5e3Sopenharmony_ci
9284514f5e3Sopenharmony_ci    Register glue(X19);
9294514f5e3Sopenharmony_ci    Register pc(X20);
9304514f5e3Sopenharmony_ci    Register fp(X5);
9314514f5e3Sopenharmony_ci    Register opcode(X6, W);
9324514f5e3Sopenharmony_ci    Register bcStub(X7);
9334514f5e3Sopenharmony_ci
9344514f5e3Sopenharmony_ci    Label dispatch;
9354514f5e3Sopenharmony_ci    __ Ldr(fp, MemoryOperand(glue, JSThread::GlueData::GetLastFpOffset(false)));
9364514f5e3Sopenharmony_ci    __ Cmp(fp, Immediate(0));
9374514f5e3Sopenharmony_ci    __ B(Condition::EQ, &dispatch);
9384514f5e3Sopenharmony_ci    // up frame
9394514f5e3Sopenharmony_ci    __ Mov(Register(SP), fp);
9404514f5e3Sopenharmony_ci    // fall through
9414514f5e3Sopenharmony_ci    __ Bind(&dispatch);
9424514f5e3Sopenharmony_ci    {
9434514f5e3Sopenharmony_ci        __ Ldrb(opcode, MemoryOperand(pc, 0));
9444514f5e3Sopenharmony_ci        __ Add(bcStub, glue, Operand(opcode, UXTW, FRAME_SLOT_SIZE_LOG2));
9454514f5e3Sopenharmony_ci        __ Ldr(bcStub, MemoryOperand(bcStub, JSThread::GlueData::GetBCStubEntriesOffset(false)));
9464514f5e3Sopenharmony_ci        __ Br(bcStub);
9474514f5e3Sopenharmony_ci    }
9484514f5e3Sopenharmony_ci}
9494514f5e3Sopenharmony_ci
9504514f5e3Sopenharmony_ci// ResumeUncaughtFrameAndReturn(uintptr_t glue)
9514514f5e3Sopenharmony_ci// GHC calling convention
9524514f5e3Sopenharmony_ci// X19 - glue
9534514f5e3Sopenharmony_ci// FP - sp
9544514f5e3Sopenharmony_ci// X20 - acc
9554514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler)
9564514f5e3Sopenharmony_ci{
9574514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(ResumeUncaughtFrameAndReturn));
9584514f5e3Sopenharmony_ci
9594514f5e3Sopenharmony_ci    Register glue(X19);
9604514f5e3Sopenharmony_ci    Register fp(X5);
9614514f5e3Sopenharmony_ci    Register acc(X20);
9624514f5e3Sopenharmony_ci    Register cppRet(X0);
9634514f5e3Sopenharmony_ci
9644514f5e3Sopenharmony_ci    __ Ldr(fp, MemoryOperand(glue, JSThread::GlueData::GetLastFpOffset(false)));
9654514f5e3Sopenharmony_ci    __ Mov(Register(SP), fp);
9664514f5e3Sopenharmony_ci    // this method will return to Execute(cpp calling convention), and the return value should be put into X0.
9674514f5e3Sopenharmony_ci    __ Mov(cppRet, acc);
9684514f5e3Sopenharmony_ci    __ RestoreFpAndLr();
9694514f5e3Sopenharmony_ci    __ Ret();
9704514f5e3Sopenharmony_ci}
9714514f5e3Sopenharmony_ci
9724514f5e3Sopenharmony_ci// ResumeRspAndRollback(uintptr_t glue, uintptr_t sp, uintptr_t pc, uintptr_t constantPool,
9734514f5e3Sopenharmony_ci//     uint64_t profileTypeInfo, uint64_t acc, uint32_t hotnessCounter, size_t jumpSize)
9744514f5e3Sopenharmony_ci// GHC calling convention
9754514f5e3Sopenharmony_ci// X19 - glue
9764514f5e3Sopenharmony_ci// FP  - sp
9774514f5e3Sopenharmony_ci// X20 - pc
9784514f5e3Sopenharmony_ci// X21 - constantPool
9794514f5e3Sopenharmony_ci// X22 - profileTypeInfo
9804514f5e3Sopenharmony_ci// X23 - acc
9814514f5e3Sopenharmony_ci// X24 - hotnessCounter
9824514f5e3Sopenharmony_ci// X25 - jumpSizeAfterCall
9834514f5e3Sopenharmony_civoid AsmInterpreterCall::ResumeRspAndRollback(ExtendedAssembler *assembler)
9844514f5e3Sopenharmony_ci{
9854514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndRollback));
9864514f5e3Sopenharmony_ci
9874514f5e3Sopenharmony_ci    Register glueRegister = __ GlueRegister();
9884514f5e3Sopenharmony_ci    Register sp(FP);
9894514f5e3Sopenharmony_ci    Register rsp(SP);
9904514f5e3Sopenharmony_ci    Register pc(X20);
9914514f5e3Sopenharmony_ci    Register jumpSizeRegister(X25);
9924514f5e3Sopenharmony_ci
9934514f5e3Sopenharmony_ci    Register ret(X23);
9944514f5e3Sopenharmony_ci    Register opcode(X6, W);
9954514f5e3Sopenharmony_ci    Register bcStub(X7);
9964514f5e3Sopenharmony_ci    Register fp(X8);
9974514f5e3Sopenharmony_ci
9984514f5e3Sopenharmony_ci    int64_t fpOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFpOffset(false))
9994514f5e3Sopenharmony_ci        - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false));
10004514f5e3Sopenharmony_ci    int64_t spOffset = static_cast<int64_t>(AsmInterpretedFrame::GetBaseOffset(false))
10014514f5e3Sopenharmony_ci        - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false));
10024514f5e3Sopenharmony_ci    int64_t funcOffset = static_cast<int64_t>(AsmInterpretedFrame::GetFunctionOffset(false))
10034514f5e3Sopenharmony_ci        - static_cast<int64_t>(AsmInterpretedFrame::GetSize(false));
10044514f5e3Sopenharmony_ci    ASSERT(fpOffset < 0);
10054514f5e3Sopenharmony_ci    ASSERT(spOffset < 0);
10064514f5e3Sopenharmony_ci    ASSERT(funcOffset < 0);
10074514f5e3Sopenharmony_ci
10084514f5e3Sopenharmony_ci    __ Ldur(fp, MemoryOperand(sp, fpOffset));  // store fp for temporary
10094514f5e3Sopenharmony_ci    __ Ldur(ret, MemoryOperand(sp, funcOffset)); // restore acc
10104514f5e3Sopenharmony_ci    __ Ldur(sp, MemoryOperand(sp, spOffset));  // update sp
10114514f5e3Sopenharmony_ci
10124514f5e3Sopenharmony_ci    __ Add(pc, pc, Operand(jumpSizeRegister, LSL, 0));
10134514f5e3Sopenharmony_ci    __ Ldrb(opcode, MemoryOperand(pc, 0));
10144514f5e3Sopenharmony_ci
10154514f5e3Sopenharmony_ci    __ Mov(rsp, fp);  // resume rsp
10164514f5e3Sopenharmony_ci    __ Add(bcStub, glueRegister, Operand(opcode, UXTW, FRAME_SLOT_SIZE_LOG2));
10174514f5e3Sopenharmony_ci    __ Ldr(bcStub, MemoryOperand(bcStub, JSThread::GlueData::GetBCStubEntriesOffset(false)));
10184514f5e3Sopenharmony_ci    __ Br(bcStub);
10194514f5e3Sopenharmony_ci}
10204514f5e3Sopenharmony_ci
10214514f5e3Sopenharmony_ci// c++ calling convention
10224514f5e3Sopenharmony_ci// X0 - glue
10234514f5e3Sopenharmony_ci// X1 - callTarget
10244514f5e3Sopenharmony_ci// X2 - method
10254514f5e3Sopenharmony_ci// X3 - callField
10264514f5e3Sopenharmony_ci// X4 - receiver
10274514f5e3Sopenharmony_ci// X5 - value
10284514f5e3Sopenharmony_civoid AsmInterpreterCall::CallGetter(ExtendedAssembler *assembler)
10294514f5e3Sopenharmony_ci{
10304514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(CallGetter));
10314514f5e3Sopenharmony_ci    Label target;
10324514f5e3Sopenharmony_ci
10334514f5e3Sopenharmony_ci    PushAsmInterpBridgeFrame(assembler);
10344514f5e3Sopenharmony_ci    __ Bl(&target);
10354514f5e3Sopenharmony_ci    PopAsmInterpBridgeFrame(assembler);
10364514f5e3Sopenharmony_ci    __ Ret();
10374514f5e3Sopenharmony_ci    __ Bind(&target);
10384514f5e3Sopenharmony_ci    {
10394514f5e3Sopenharmony_ci        JSCallCommonEntry(assembler, JSCallMode::CALL_GETTER, FrameTransitionType::OTHER_TO_OTHER);
10404514f5e3Sopenharmony_ci    }
10414514f5e3Sopenharmony_ci}
10424514f5e3Sopenharmony_ci
10434514f5e3Sopenharmony_civoid AsmInterpreterCall::CallSetter(ExtendedAssembler *assembler)
10444514f5e3Sopenharmony_ci{
10454514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(CallSetter));
10464514f5e3Sopenharmony_ci    Label target;
10474514f5e3Sopenharmony_ci    PushAsmInterpBridgeFrame(assembler);
10484514f5e3Sopenharmony_ci    __ Bl(&target);
10494514f5e3Sopenharmony_ci    PopAsmInterpBridgeFrame(assembler);
10504514f5e3Sopenharmony_ci    __ Ret();
10514514f5e3Sopenharmony_ci    __ Bind(&target);
10524514f5e3Sopenharmony_ci    {
10534514f5e3Sopenharmony_ci        JSCallCommonEntry(assembler, JSCallMode::CALL_SETTER, FrameTransitionType::OTHER_TO_OTHER);
10544514f5e3Sopenharmony_ci    }
10554514f5e3Sopenharmony_ci}
10564514f5e3Sopenharmony_ci
10574514f5e3Sopenharmony_civoid AsmInterpreterCall::CallContainersArgs2(ExtendedAssembler *assembler)
10584514f5e3Sopenharmony_ci{
10594514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(CallContainersArgs2));
10604514f5e3Sopenharmony_ci    Label target;
10614514f5e3Sopenharmony_ci    PushAsmInterpBridgeFrame(assembler);
10624514f5e3Sopenharmony_ci    __ Bl(&target);
10634514f5e3Sopenharmony_ci    PopAsmInterpBridgeFrame(assembler);
10644514f5e3Sopenharmony_ci    __ Ret();
10654514f5e3Sopenharmony_ci    __ Bind(&target);
10664514f5e3Sopenharmony_ci    {
10674514f5e3Sopenharmony_ci        JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG2_WITH_RETURN,
10684514f5e3Sopenharmony_ci                          FrameTransitionType::OTHER_TO_OTHER);
10694514f5e3Sopenharmony_ci    }
10704514f5e3Sopenharmony_ci}
10714514f5e3Sopenharmony_ci
10724514f5e3Sopenharmony_civoid AsmInterpreterCall::CallContainersArgs3(ExtendedAssembler *assembler)
10734514f5e3Sopenharmony_ci{
10744514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(CallContainersArgs3));
10754514f5e3Sopenharmony_ci    Label target;
10764514f5e3Sopenharmony_ci    PushAsmInterpBridgeFrame(assembler);
10774514f5e3Sopenharmony_ci    __ Bl(&target);
10784514f5e3Sopenharmony_ci    PopAsmInterpBridgeFrame(assembler);
10794514f5e3Sopenharmony_ci    __ Ret();
10804514f5e3Sopenharmony_ci    __ Bind(&target);
10814514f5e3Sopenharmony_ci    {
10824514f5e3Sopenharmony_ci        JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARG3_WITH_RETURN,
10834514f5e3Sopenharmony_ci                          FrameTransitionType::OTHER_TO_OTHER);
10844514f5e3Sopenharmony_ci    }
10854514f5e3Sopenharmony_ci}
10864514f5e3Sopenharmony_ci
10874514f5e3Sopenharmony_ci// c++ calling convention
10884514f5e3Sopenharmony_ci// X0 - glue
10894514f5e3Sopenharmony_ci// X1 - callTarget
10904514f5e3Sopenharmony_ci// X2 - method
10914514f5e3Sopenharmony_ci// X3 - callField
10924514f5e3Sopenharmony_ci// X4 - arg0(argc)
10934514f5e3Sopenharmony_ci// X5 - arg1(arglist)
10944514f5e3Sopenharmony_ci// X6 - arg3(argthis)
10954514f5e3Sopenharmony_civoid AsmInterpreterCall::CallReturnWithArgv(ExtendedAssembler *assembler)
10964514f5e3Sopenharmony_ci{
10974514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(CallReturnWithArgv));
10984514f5e3Sopenharmony_ci    Label target;
10994514f5e3Sopenharmony_ci    PushAsmInterpBridgeFrame(assembler);
11004514f5e3Sopenharmony_ci    __ Bl(&target);
11014514f5e3Sopenharmony_ci    PopAsmInterpBridgeFrame(assembler);
11024514f5e3Sopenharmony_ci    __ Ret();
11034514f5e3Sopenharmony_ci    __ Bind(&target);
11044514f5e3Sopenharmony_ci    {
11054514f5e3Sopenharmony_ci        JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_ARGV_WITH_RETURN,
11064514f5e3Sopenharmony_ci                          FrameTransitionType::OTHER_TO_OTHER);
11074514f5e3Sopenharmony_ci    }
11084514f5e3Sopenharmony_ci}
11094514f5e3Sopenharmony_ci
11104514f5e3Sopenharmony_ci// preserve all the general registers, except x15 and callee saved registers/
11114514f5e3Sopenharmony_ci// and call x15
11124514f5e3Sopenharmony_civoid AsmInterpreterCall::PreserveMostCall(ExtendedAssembler* assembler)
11134514f5e3Sopenharmony_ci{
11144514f5e3Sopenharmony_ci    // * layout as the following:
11154514f5e3Sopenharmony_ci    //               +--------------------------+ ---------
11164514f5e3Sopenharmony_ci    //               |       . . . . .          |         ^
11174514f5e3Sopenharmony_ci    // callerSP ---> |--------------------------|         |
11184514f5e3Sopenharmony_ci    //               |       returnAddr         |         |
11194514f5e3Sopenharmony_ci    //               |--------------------------|   OptimizedFrame
11204514f5e3Sopenharmony_ci    //               |       callsiteFp         |         |
11214514f5e3Sopenharmony_ci    //       fp ---> |--------------------------|         |
11224514f5e3Sopenharmony_ci    //               |     OPTIMIZED_FRAME      |         v
11234514f5e3Sopenharmony_ci    //               +--------------------------+ ---------
11244514f5e3Sopenharmony_ci    //               |           x0             |
11254514f5e3Sopenharmony_ci    //               +--------------------------+
11264514f5e3Sopenharmony_ci    //               |           x1             |
11274514f5e3Sopenharmony_ci    //               +--------------------------+
11284514f5e3Sopenharmony_ci    //               |           r2             |
11294514f5e3Sopenharmony_ci    //               +--------------------------+
11304514f5e3Sopenharmony_ci    //               |           x3             |
11314514f5e3Sopenharmony_ci    //               +--------------------------+
11324514f5e3Sopenharmony_ci    //               |           x4             |
11334514f5e3Sopenharmony_ci    //               +--------------------------+
11344514f5e3Sopenharmony_ci    //               |           x5             |
11354514f5e3Sopenharmony_ci    //               +--------------------------+
11364514f5e3Sopenharmony_ci    //               |           x6             |
11374514f5e3Sopenharmony_ci    //               +--------------------------+
11384514f5e3Sopenharmony_ci    //               |           x7             |
11394514f5e3Sopenharmony_ci    //               +--------------------------+
11404514f5e3Sopenharmony_ci    //               |           x8             |
11414514f5e3Sopenharmony_ci    //               +--------------------------+
11424514f5e3Sopenharmony_ci    //               |           x9             |
11434514f5e3Sopenharmony_ci    //               +--------------------------+
11444514f5e3Sopenharmony_ci    //               |           x10            |
11454514f5e3Sopenharmony_ci    //               +--------------------------+
11464514f5e3Sopenharmony_ci    //               |           x11            |
11474514f5e3Sopenharmony_ci    //               +--------------------------+
11484514f5e3Sopenharmony_ci    //               |           x12            |
11494514f5e3Sopenharmony_ci    //               +--------------------------+
11504514f5e3Sopenharmony_ci    //               |           x13            |
11514514f5e3Sopenharmony_ci    //               +--------------------------+
11524514f5e3Sopenharmony_ci    //               |           x14            |
11534514f5e3Sopenharmony_ci    //               +--------------------------+
11544514f5e3Sopenharmony_ci    //               |           x16            |
11554514f5e3Sopenharmony_ci    //               +--------------------------+
11564514f5e3Sopenharmony_ci    //               |           x17            |
11574514f5e3Sopenharmony_ci    //               +--------------------------+
11584514f5e3Sopenharmony_ci    //               |           x18            |
11594514f5e3Sopenharmony_ci    //               +--------------------------+
11604514f5e3Sopenharmony_ci    //               |         align            |
11614514f5e3Sopenharmony_ci    // calleeSP ---> +--------------------------+
11624514f5e3Sopenharmony_ci    {
11634514f5e3Sopenharmony_ci        // prologue to save fp, frametype, and update fp.
11644514f5e3Sopenharmony_ci        __ Stp(X29, X30, MemoryOperand(SP, -DOUBLE_SLOT_SIZE, PREINDEX));
11654514f5e3Sopenharmony_ci        // Zero register means OPTIMIZED_FRAME
11664514f5e3Sopenharmony_ci        __ Stp(X0, Zero, MemoryOperand(SP, -DOUBLE_SLOT_SIZE, PREINDEX));
11674514f5e3Sopenharmony_ci        __ Add(FP, SP, Immediate(DOUBLE_SLOT_SIZE));
11684514f5e3Sopenharmony_ci    }
11694514f5e3Sopenharmony_ci    int32_t PreserveRegPairIndex = 9;
11704514f5e3Sopenharmony_ci    // x0~x14,x16,x17,x18 should be preserved,
11714514f5e3Sopenharmony_ci    // other general registers are callee saved register, callee will save them.
11724514f5e3Sopenharmony_ci    __ Sub(SP, SP, Immediate(DOUBLE_SLOT_SIZE * PreserveRegPairIndex));
11734514f5e3Sopenharmony_ci    __ Stp(X1, X2, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex)));
11744514f5e3Sopenharmony_ci    __ Stp(X3, X4, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex)));
11754514f5e3Sopenharmony_ci    __ Stp(X5, X6, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex)));
11764514f5e3Sopenharmony_ci    __ Stp(X7, X8, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex)));
11774514f5e3Sopenharmony_ci    __ Stp(X9, X10, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex)));
11784514f5e3Sopenharmony_ci    __ Stp(X11, X12, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex)));
11794514f5e3Sopenharmony_ci    __ Stp(X13, X14, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex)));
11804514f5e3Sopenharmony_ci    __ Stp(X16, X17, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (--PreserveRegPairIndex)));
11814514f5e3Sopenharmony_ci    __ Str(X18, MemoryOperand(SP, FRAME_SLOT_SIZE));
11824514f5e3Sopenharmony_ci    __ Blr(X15);
11834514f5e3Sopenharmony_ci    __ Ldr(X18, MemoryOperand(SP, FRAME_SLOT_SIZE));
11844514f5e3Sopenharmony_ci    __ Ldp(X16, X17, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++)));
11854514f5e3Sopenharmony_ci    __ Ldp(X13, X14, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++)));
11864514f5e3Sopenharmony_ci    __ Ldp(X11, X12, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++)));
11874514f5e3Sopenharmony_ci    __ Ldp(X9, X10, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++)));
11884514f5e3Sopenharmony_ci    __ Ldp(X7, X8, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++)));
11894514f5e3Sopenharmony_ci    __ Ldp(X5, X6, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++)));
11904514f5e3Sopenharmony_ci    __ Ldp(X3, X4, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++)));
11914514f5e3Sopenharmony_ci    __ Ldp(X1, X2, MemoryOperand(SP, DOUBLE_SLOT_SIZE * (PreserveRegPairIndex++)));
11924514f5e3Sopenharmony_ci    __ Ldr(X0, MemoryOperand(SP, DOUBLE_SLOT_SIZE * PreserveRegPairIndex));
11934514f5e3Sopenharmony_ci    {
11944514f5e3Sopenharmony_ci        // epilogue to restore sp, fp, lr.
11954514f5e3Sopenharmony_ci        // Skip x0 slot and frametype slot
11964514f5e3Sopenharmony_ci        __ Add(SP, SP, Immediate(DOUBLE_SLOT_SIZE * PreserveRegPairIndex +
11974514f5e3Sopenharmony_ci            FRAME_SLOT_SIZE + FRAME_SLOT_SIZE));
11984514f5e3Sopenharmony_ci        __ Ldp(FP, X30, MemoryOperand(SP, DOUBLE_SLOT_SIZE, AddrMode::POSTINDEX));
11994514f5e3Sopenharmony_ci        __ Ret();
12004514f5e3Sopenharmony_ci    }
12014514f5e3Sopenharmony_ci}
12024514f5e3Sopenharmony_ci
12034514f5e3Sopenharmony_ci// ASMFastWriteBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value)
12044514f5e3Sopenharmony_ci// c calling convention, but preserve all general registers except %x15
12054514f5e3Sopenharmony_ci// %x0 - glue
12064514f5e3Sopenharmony_ci// %x1 - obj
12074514f5e3Sopenharmony_ci// %x2 - offset
12084514f5e3Sopenharmony_ci// %x3 - value
12094514f5e3Sopenharmony_civoid AsmInterpreterCall::ASMFastWriteBarrier(ExtendedAssembler* assembler)
12104514f5e3Sopenharmony_ci{
12114514f5e3Sopenharmony_ci    // valid region flag are as follows, assume it will be ALWAYS VALID.
12124514f5e3Sopenharmony_ci    // Judge the region of value with:
12134514f5e3Sopenharmony_ci    //                          "young"            "sweepable share"  "readonly share"
12144514f5e3Sopenharmony_ci    // region flag:         0x08, 0x09, [0x0A, 0x11], [0x12, 0x15],     0x16
12154514f5e3Sopenharmony_ci    // value is share:                                [0x12,            0x16] =>  valueMaybeSweepableShare
12164514f5e3Sopenharmony_ci    // readonly share:                                                  0x16  =>  return
12174514f5e3Sopenharmony_ci    // sweepable share:                               [0x12, 0x15]            =>  needShareBarrier
12184514f5e3Sopenharmony_ci    // value is not share:  0x08, 0x09, [0x0A, 0x11],                         =>  valueNotShare
12194514f5e3Sopenharmony_ci    // value is young :           0x09                                        =>  needCallNotShare
12204514f5e3Sopenharmony_ci    // value is not young : 0x08,       [0x0A, 0x11],                         =>  checkMark
12214514f5e3Sopenharmony_ci    ASSERT(GENERAL_YOUNG_BEGIN <= IN_YOUNG_SPACE && IN_YOUNG_SPACE < SHARED_SPACE_BEGIN &&
12224514f5e3Sopenharmony_ci        SHARED_SPACE_BEGIN <= SHARED_SWEEPABLE_SPACE_BEGIN && SHARED_SWEEPABLE_SPACE_END < IN_SHARED_READ_ONLY_SPACE &&
12234514f5e3Sopenharmony_ci        IN_SHARED_READ_ONLY_SPACE == HEAP_SPACE_END);
12244514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(ASMFastWriteBarrier));
12254514f5e3Sopenharmony_ci    Label needCall;
12264514f5e3Sopenharmony_ci    Label checkMark;
12274514f5e3Sopenharmony_ci    Label needCallNotShare;
12284514f5e3Sopenharmony_ci    Label needShareBarrier;
12294514f5e3Sopenharmony_ci    Label valueNotShare;
12304514f5e3Sopenharmony_ci    Label valueMaybeSweepableShare;
12314514f5e3Sopenharmony_ci    {
12324514f5e3Sopenharmony_ci        // int8_t *valueRegion = value & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK))
12334514f5e3Sopenharmony_ci        // int8_t valueFlag = *valueRegion
12344514f5e3Sopenharmony_ci        // if (valueFlag >= SHARED_SWEEPABLE_SPACE_BEGIN){
12354514f5e3Sopenharmony_ci        //    goto valueMaybeSweepableShare
12364514f5e3Sopenharmony_ci        // }
12374514f5e3Sopenharmony_ci
12384514f5e3Sopenharmony_ci        __ And(X15, X3, LogicalImmediate::Create(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), RegXSize));
12394514f5e3Sopenharmony_ci        // X15 is the region address of value.
12404514f5e3Sopenharmony_ci        __ Ldrb(Register(X15, W), MemoryOperand(X15, 0));
12414514f5e3Sopenharmony_ci        // X15 is the flag load from region of value.
12424514f5e3Sopenharmony_ci        __ Cmp(Register(X15, W), Immediate(SHARED_SWEEPABLE_SPACE_BEGIN));
12434514f5e3Sopenharmony_ci        __ B(GE, &valueMaybeSweepableShare);
12444514f5e3Sopenharmony_ci        // if value may be SweepableShare, goto valueMaybeSweepableShare
12454514f5e3Sopenharmony_ci    }
12464514f5e3Sopenharmony_ci    __ Bind(&valueNotShare);
12474514f5e3Sopenharmony_ci    {
12484514f5e3Sopenharmony_ci        // valueNotShare:
12494514f5e3Sopenharmony_ci        // if (valueFlag != IN_YOUNG_SPACE){
12504514f5e3Sopenharmony_ci        //      goto checkMark
12514514f5e3Sopenharmony_ci        // }
12524514f5e3Sopenharmony_ci        // int8_t *objRegion = obj & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK))
12534514f5e3Sopenharmony_ci        // int8_t objFlag = *objRegion
12544514f5e3Sopenharmony_ci        // if (objFlag != IN_YOUNG_SPACE){
12554514f5e3Sopenharmony_ci        //    goto needCallNotShare
12564514f5e3Sopenharmony_ci        // }
12574514f5e3Sopenharmony_ci
12584514f5e3Sopenharmony_ci        __ Cmp(Register(X15, W), Immediate(RegionSpaceFlag::IN_YOUNG_SPACE));
12594514f5e3Sopenharmony_ci        __ B(NE, &checkMark);
12604514f5e3Sopenharmony_ci        // if value is not in young, goto checkMark
12614514f5e3Sopenharmony_ci
12624514f5e3Sopenharmony_ci        __ And(X15, X1, LogicalImmediate::Create(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), RegXSize));
12634514f5e3Sopenharmony_ci        // X15 is the region address of obj.
12644514f5e3Sopenharmony_ci        __ Ldrb(Register(X15, W), MemoryOperand(X15, 0));
12654514f5e3Sopenharmony_ci        // X15 is the flag load from region of obj.
12664514f5e3Sopenharmony_ci        __ Cmp(Register(X15, W), Immediate(RegionSpaceFlag::IN_YOUNG_SPACE));
12674514f5e3Sopenharmony_ci        __ B(NE, &needCallNotShare);
12684514f5e3Sopenharmony_ci        // if obj is not in young, goto needCallNotShare
12694514f5e3Sopenharmony_ci    }
12704514f5e3Sopenharmony_ci
12714514f5e3Sopenharmony_ci    __ Bind(&checkMark);
12724514f5e3Sopenharmony_ci    {
12734514f5e3Sopenharmony_ci        // checkMark:
12744514f5e3Sopenharmony_ci        // int8_t GCStateBitField = *(glue+GCStateBitFieldOffset)
12754514f5e3Sopenharmony_ci        // if (GCStateBitField & JSThread::CONCURRENT_MARKING_BITFIELD_MASK != 0) {
12764514f5e3Sopenharmony_ci        //    goto needCallNotShare
12774514f5e3Sopenharmony_ci        // }
12784514f5e3Sopenharmony_ci        // return
12794514f5e3Sopenharmony_ci
12804514f5e3Sopenharmony_ci        __ Mov(X15, JSThread::GlueData::GetGCStateBitFieldOffset(false));
12814514f5e3Sopenharmony_ci        __ Ldrb(Register(X15, W), MemoryOperand(X0, Register(X15), UXTX));
12824514f5e3Sopenharmony_ci        __ Tst(Register(X15, W), LogicalImmediate::Create(JSThread::CONCURRENT_MARKING_BITFIELD_MASK, RegWSize));
12834514f5e3Sopenharmony_ci        __ B(NE, &needCallNotShare);
12844514f5e3Sopenharmony_ci        // if GCState is not READY_TO_MARK, go to needCallNotShare.
12854514f5e3Sopenharmony_ci        __ Ret();
12864514f5e3Sopenharmony_ci    }
12874514f5e3Sopenharmony_ci
12884514f5e3Sopenharmony_ci    __ Bind(&valueMaybeSweepableShare);
12894514f5e3Sopenharmony_ci    {
12904514f5e3Sopenharmony_ci        // valueMaybeSweepableShare:
12914514f5e3Sopenharmony_ci        // if (valueFlag != IN_SHARED_READ_ONLY_SPACE){
12924514f5e3Sopenharmony_ci        //    goto needShareBarrier
12934514f5e3Sopenharmony_ci        // }
12944514f5e3Sopenharmony_ci        // return
12954514f5e3Sopenharmony_ci        __ Cmp(Register(X15, W), Immediate(RegionSpaceFlag::IN_SHARED_READ_ONLY_SPACE));
12964514f5e3Sopenharmony_ci        __ B(NE, &needShareBarrier);
12974514f5e3Sopenharmony_ci        __ Ret();
12984514f5e3Sopenharmony_ci    }
12994514f5e3Sopenharmony_ci
13004514f5e3Sopenharmony_ci    __ Bind(&needCallNotShare);
13014514f5e3Sopenharmony_ci    {
13024514f5e3Sopenharmony_ci        int32_t NonSValueBarrier = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) +
13034514f5e3Sopenharmony_ci            kungfu::CommonStubCSigns::SetNonSValueWithBarrier * FRAME_SLOT_SIZE;
13044514f5e3Sopenharmony_ci        __ Mov(X15, NonSValueBarrier);
13054514f5e3Sopenharmony_ci    }
13064514f5e3Sopenharmony_ci    __ Bind(&needCall);
13074514f5e3Sopenharmony_ci    {
13084514f5e3Sopenharmony_ci        __ Ldr(X15, MemoryOperand(X0, Register(X15), UXTX));
13094514f5e3Sopenharmony_ci        PreserveMostCall(assembler);
13104514f5e3Sopenharmony_ci    }
13114514f5e3Sopenharmony_ci    __ Bind(&needShareBarrier);
13124514f5e3Sopenharmony_ci    {
13134514f5e3Sopenharmony_ci        ASMFastSharedWriteBarrier(assembler, needCall);
13144514f5e3Sopenharmony_ci    }
13154514f5e3Sopenharmony_ci}
13164514f5e3Sopenharmony_ci
13174514f5e3Sopenharmony_ci// ASMWriteBarrierWithEden(GateRef glue, GateRef obj, GateRef offset, GateRef value)
13184514f5e3Sopenharmony_ci// c calling convention, but preserve all general registers except %x15
13194514f5e3Sopenharmony_ci// %x0 - glue
13204514f5e3Sopenharmony_ci// %x1 - obj
13214514f5e3Sopenharmony_ci// %x2 - offset
13224514f5e3Sopenharmony_ci// %x3 - value
13234514f5e3Sopenharmony_civoid AsmInterpreterCall::ASMWriteBarrierWithEden(ExtendedAssembler* assembler)
13244514f5e3Sopenharmony_ci{
13254514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(ASMWriteBarrierWithEden));
13264514f5e3Sopenharmony_ci    // Just for compitability, not a fast implement, should be refactored when enable EdenBarrier.
13274514f5e3Sopenharmony_ci    int32_t EdenBarrierOffset = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) +
13284514f5e3Sopenharmony_ci    kungfu::CommonStubCSigns::SetValueWithEdenBarrier * FRAME_SLOT_SIZE;
13294514f5e3Sopenharmony_ci    __ Mov(X15, EdenBarrierOffset);
13304514f5e3Sopenharmony_ci    __ Ldr(X15, MemoryOperand(X0, Register(X15), UXTX));
13314514f5e3Sopenharmony_ci    PreserveMostCall(assembler);
13324514f5e3Sopenharmony_ci}
13334514f5e3Sopenharmony_ci
13344514f5e3Sopenharmony_ci// %x0 - glue
13354514f5e3Sopenharmony_ci// %x1 - obj
13364514f5e3Sopenharmony_ci// %x2 - offset
13374514f5e3Sopenharmony_ci// %x3 - value
13384514f5e3Sopenharmony_civoid AsmInterpreterCall::ASMFastSharedWriteBarrier(ExtendedAssembler* assembler, Label& needCall)
13394514f5e3Sopenharmony_ci{
13404514f5e3Sopenharmony_ci    Label checkBarrierForSharedValue;
13414514f5e3Sopenharmony_ci    Label restoreScratchRegister;
13424514f5e3Sopenharmony_ci    Label callSharedBarrier;
13434514f5e3Sopenharmony_ci    {
13444514f5e3Sopenharmony_ci        // int8_t *objRegion = obj & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK))
13454514f5e3Sopenharmony_ci        // int8_t objFlag = *objRegion
13464514f5e3Sopenharmony_ci        // if (objFlag >= SHARED_SPACE_BEGIN){
13474514f5e3Sopenharmony_ci        //    // share to share, just check the barrier
13484514f5e3Sopenharmony_ci        //    goto checkBarrierForSharedValue
13494514f5e3Sopenharmony_ci        // }
13504514f5e3Sopenharmony_ci        __ And(X15, X1, LogicalImmediate::Create(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), RegXSize));
13514514f5e3Sopenharmony_ci        __ Ldrb(Register(X15, W), MemoryOperand(X15, 0));
13524514f5e3Sopenharmony_ci        // X15 is the flag load from region of obj.
13534514f5e3Sopenharmony_ci        __ Cmp(Register(X15, W), Immediate(RegionSpaceFlag::SHARED_SPACE_BEGIN));
13544514f5e3Sopenharmony_ci        __ B(GE, &checkBarrierForSharedValue);  // if objflag >= SHARED_SPACE_BEGIN  => checkBarrierForSharedValue
13554514f5e3Sopenharmony_ci    }
13564514f5e3Sopenharmony_ci    {
13574514f5e3Sopenharmony_ci        // int8_t *objRegion = obj & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK))
13584514f5e3Sopenharmony_ci        // int8_t *localToShareSet = *(objRegion + LocalToShareSetOffset)
13594514f5e3Sopenharmony_ci        // if (localToShareSet == 0){
13604514f5e3Sopenharmony_ci        //    goto callSharedBarrier
13614514f5e3Sopenharmony_ci        // }
13624514f5e3Sopenharmony_ci        __ And(X15, X1, LogicalImmediate::Create(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), RegXSize));
13634514f5e3Sopenharmony_ci        __ Ldr(X15, MemoryOperand(X15, Region::PackedData::GetLocalToShareSetOffset(false)));
13644514f5e3Sopenharmony_ci        // X15 is localToShareSet for obj region.
13654514f5e3Sopenharmony_ci        __ Cbz({X15, X}, &callSharedBarrier);   // if localToShareSet == 0  => callSharedBarrier
13664514f5e3Sopenharmony_ci    }
13674514f5e3Sopenharmony_ci    {
13684514f5e3Sopenharmony_ci        // X16, X17 will be used as scratch register, spill them.
13694514f5e3Sopenharmony_ci        // the caller will call this function with inline asm, it will not save any registers except x15.
13704514f5e3Sopenharmony_ci        // So we need spill and restore x16, x17 when we need them as scratch register.
13714514f5e3Sopenharmony_ci        {
13724514f5e3Sopenharmony_ci            __ Stp(X16, X17, MemoryOperand(SP, -DOUBLE_SLOT_SIZE, PREINDEX));
13734514f5e3Sopenharmony_ci        }
13744514f5e3Sopenharmony_ci        // int64_t objOffset = obj & DEFAULT_REGION_MASK
13754514f5e3Sopenharmony_ci        // int64_t slotOffset = objOffset + offset
13764514f5e3Sopenharmony_ci        __ And(X16, X1, LogicalImmediate::Create(DEFAULT_REGION_MASK, RegXSize));
13774514f5e3Sopenharmony_ci        __ Add(X16, X16, Operand(Register(X2)));
13784514f5e3Sopenharmony_ci
13794514f5e3Sopenharmony_ci        // the logic to get mask in stub_builder.cpp
13804514f5e3Sopenharmony_ci        //               [63-------------------------35][34------------------------8][7---3][2-0]
13814514f5e3Sopenharmony_ci        // bitOffset:                                       bbbbbbbbbbbbbbbbbbbbbbbb  bbbcc  ccc
13824514f5e3Sopenharmony_ci        // bitPerWordMask:                                                               11  111
13834514f5e3Sopenharmony_ci        // indexInWord = And bitoffset bitPerWordMask
13844514f5e3Sopenharmony_ci        // indexInWord:                                                                  cc  ccc
13854514f5e3Sopenharmony_ci        // mask = 1 << indexInWord
13864514f5e3Sopenharmony_ci
13874514f5e3Sopenharmony_ci        // the logic to test bit set value here:
13884514f5e3Sopenharmony_ci        //               [63-------------------------35][34------------------------8][7---3][2-0]
13894514f5e3Sopenharmony_ci        // slotOffset:    aaaaaaaaaaaaaaaaaaaaaaaaaaaaa  bbbbbbbbbbbbbbbbbbbbbbbbbbb  ccccc  ddd
13904514f5e3Sopenharmony_ci        // Ubfm X16 slotOffset 3 7
13914514f5e3Sopenharmony_ci        // indexInWord:                                                                  cc  ccc
13924514f5e3Sopenharmony_ci        __ Ubfm(X17, X16, TAGGED_TYPE_SIZE_LOG, TAGGED_TYPE_SIZE_LOG + GCBitset::BIT_PER_WORD_LOG2 - 1);
13934514f5e3Sopenharmony_ci
13944514f5e3Sopenharmony_ci        // the logic to get byteIndex in stub_builder.cpp
13954514f5e3Sopenharmony_ci        //               [63-------------------------35][34------------------------8][7---3][2-0]
13964514f5e3Sopenharmony_ci        // slotOffset:    aaaaaaaaaaaaaaaaaaaaaaaaaaaaa  bbbbbbbbbbbbbbbbbbbbbbbbbbb  ccccc  ddd
13974514f5e3Sopenharmony_ci        // 1. bitOffsetPtr = LSR TAGGED_TYPE_SIZE_LOG(3) slotOffset
13984514f5e3Sopenharmony_ci        // bitOffsetPtr:     aaaaaaaaaaaaaaaaaaaaaaaaaa  aaabbbbbbbbbbbbbbbbbbbbbbbb  bbbcc  ccc
13994514f5e3Sopenharmony_ci        // 2. bitOffset = TruncPtrToInt32 bitOffsetPtr
14004514f5e3Sopenharmony_ci        // bitOffset:                                       bbbbbbbbbbbbbbbbbbbbbbbb  bbbcc  ccc
14014514f5e3Sopenharmony_ci        // 3. index = LSR BIT_PER_WORD_LOG2(5) bitOffset
14024514f5e3Sopenharmony_ci        // index:                                                bbbbbbbbbbbbbbbbbbb  bbbbb  bbb
14034514f5e3Sopenharmony_ci        // 4. byteIndex = Mul index BYTE_PER_WORD(4)
14044514f5e3Sopenharmony_ci        // byteIndex:                                          bbbbbbbbbbbbbbbbbbbbb  bbbbb  b00
14054514f5e3Sopenharmony_ci
14064514f5e3Sopenharmony_ci        // the logic to get byteIndex here:
14074514f5e3Sopenharmony_ci        //               [63-------------------------35][34------------------------8][7---3][2-0]
14084514f5e3Sopenharmony_ci        // slotOffset:    aaaaaaaaaaaaaaaaaaaaaaaaaaaaa  bbbbbbbbbbbbbbbbbbbbbbbbbbb  ccccc  ddd
14094514f5e3Sopenharmony_ci        // Ubfm X16 slotOffset 8 34
14104514f5e3Sopenharmony_ci        // index:                                                bbbbbbbbbbbbbbbbbbb  bbbbb  bbb
14114514f5e3Sopenharmony_ci        __ Ubfm(X16, X16, TAGGED_TYPE_SIZE_LOG + GCBitset::BIT_PER_WORD_LOG2,
14124514f5e3Sopenharmony_ci                sizeof(uint32_t) * GCBitset::BIT_PER_BYTE + TAGGED_TYPE_SIZE_LOG - 1);
14134514f5e3Sopenharmony_ci        __ Add(X15, X15, Operand(Register(X16), LSL, GCBitset::BYTE_PER_WORD_LOG2));
14144514f5e3Sopenharmony_ci        __ Add(X15, X15, Immediate(RememberedSet::GCBITSET_DATA_OFFSET));
14154514f5e3Sopenharmony_ci        // X15 is the address of bitset value. X15 = X15 + X16 << BYTE_PER_WORD_LOG2 + GCBITSET_DATA_OFFSET
14164514f5e3Sopenharmony_ci
14174514f5e3Sopenharmony_ci        // mask = 1 << indexInWord
14184514f5e3Sopenharmony_ci        __ Mov(Register(X16, W), 1);
14194514f5e3Sopenharmony_ci        __ Lsl(Register(X17, W), Register(X16, W), Register(X17, W)); // X17 is the mask
14204514f5e3Sopenharmony_ci
14214514f5e3Sopenharmony_ci        __ Ldr(Register(X16, W), MemoryOperand(X15, 0)); // x16: oldsetValue
14224514f5e3Sopenharmony_ci        __ Tst(Register(X16, W), Register(X17, W));
14234514f5e3Sopenharmony_ci        __ B(NE, &restoreScratchRegister);
14244514f5e3Sopenharmony_ci        __ Orr(Register(X16, W), Register(X16, W), Register(X17, W));
14254514f5e3Sopenharmony_ci        __ Str(Register(X16, W), MemoryOperand(X15, 0));
14264514f5e3Sopenharmony_ci    }
14274514f5e3Sopenharmony_ci    __ Bind(&restoreScratchRegister);
14284514f5e3Sopenharmony_ci    {
14294514f5e3Sopenharmony_ci        __ Ldp(X16, X17, MemoryOperand(SP, DOUBLE_SLOT_SIZE, POSTINDEX));
14304514f5e3Sopenharmony_ci    }
14314514f5e3Sopenharmony_ci    __ Bind(&checkBarrierForSharedValue);
14324514f5e3Sopenharmony_ci    {
14334514f5e3Sopenharmony_ci        // checkBarrierForSharedValue:
14344514f5e3Sopenharmony_ci        // int8_t GCStateBitField = *(glue+SharedGCStateBitFieldOffset)
14354514f5e3Sopenharmony_ci        // if (GCStateBitField & JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK != 0) {
14364514f5e3Sopenharmony_ci        //    goto callSharedBarrier
14374514f5e3Sopenharmony_ci        // }
14384514f5e3Sopenharmony_ci        // return
14394514f5e3Sopenharmony_ci        __ Mov(X15, JSThread::GlueData::GetSharedGCStateBitFieldOffset(false));
14404514f5e3Sopenharmony_ci        __ Ldrb(Register(X15, W), MemoryOperand(X0, Register(X15), UXTX));
14414514f5e3Sopenharmony_ci        static_assert(JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK == 1 && "Tbnz can't handle other bit mask");
14424514f5e3Sopenharmony_ci        __ Tbnz(Register(X15, W), 0, &callSharedBarrier);
14434514f5e3Sopenharmony_ci        // if GCState is not READY_TO_MARK, go to needCallNotShare.
14444514f5e3Sopenharmony_ci        __ Ret();
14454514f5e3Sopenharmony_ci    }
14464514f5e3Sopenharmony_ci
14474514f5e3Sopenharmony_ci    __ Bind(&callSharedBarrier);
14484514f5e3Sopenharmony_ci    {
14494514f5e3Sopenharmony_ci        int32_t SValueBarrierOffset = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) +
14504514f5e3Sopenharmony_ci            kungfu::CommonStubCSigns::SetSValueWithBarrier * FRAME_SLOT_SIZE;
14514514f5e3Sopenharmony_ci        __ Mov(X15, SValueBarrierOffset);
14524514f5e3Sopenharmony_ci        __ B(&needCall);
14534514f5e3Sopenharmony_ci    }
14544514f5e3Sopenharmony_ci}
14554514f5e3Sopenharmony_ci
14564514f5e3Sopenharmony_ci// Generate code for generator re-entering asm interpreter
14574514f5e3Sopenharmony_ci// c++ calling convention
14584514f5e3Sopenharmony_ci// Input: %X0 - glue
14594514f5e3Sopenharmony_ci//        %X1 - context(GeneratorContext)
14604514f5e3Sopenharmony_civoid AsmInterpreterCall::GeneratorReEnterAsmInterp(ExtendedAssembler *assembler)
14614514f5e3Sopenharmony_ci{
14624514f5e3Sopenharmony_ci    __ BindAssemblerStub(RTSTUB_ID(GeneratorReEnterAsmInterp));
14634514f5e3Sopenharmony_ci    Label target;
14644514f5e3Sopenharmony_ci    size_t begin = __ GetCurrentPosition();
14654514f5e3Sopenharmony_ci    PushAsmInterpEntryFrame(assembler);
14664514f5e3Sopenharmony_ci    __ Bl(&target);
14674514f5e3Sopenharmony_ci    PopAsmInterpEntryFrame(assembler);
14684514f5e3Sopenharmony_ci    size_t end = __ GetCurrentPosition();
14694514f5e3Sopenharmony_ci    if ((end - begin) != FrameCompletionPos::ARM64EntryFrameDuration) {
14704514f5e3Sopenharmony_ci        LOG_COMPILER(FATAL) << (end - begin) << " != " << FrameCompletionPos::ARM64EntryFrameDuration
14714514f5e3Sopenharmony_ci                            << "This frame has been modified, and the offset EntryFrameDuration should be updated too.";
14724514f5e3Sopenharmony_ci    }
14734514f5e3Sopenharmony_ci    __ Ret();
14744514f5e3Sopenharmony_ci    __ Bind(&target);
14754514f5e3Sopenharmony_ci    {
14764514f5e3Sopenharmony_ci        GeneratorReEnterAsmInterpDispatch(assembler);
14774514f5e3Sopenharmony_ci    }
14784514f5e3Sopenharmony_ci}
14794514f5e3Sopenharmony_ci
14804514f5e3Sopenharmony_civoid AsmInterpreterCall::GeneratorReEnterAsmInterpDispatch(ExtendedAssembler *assembler)
14814514f5e3Sopenharmony_ci{
14824514f5e3Sopenharmony_ci    Label pushFrameState;
14834514f5e3Sopenharmony_ci    Label stackOverflow;
14844514f5e3Sopenharmony_ci    Register glue = __ GlueRegister();
14854514f5e3Sopenharmony_ci    Register contextRegister(X1);
14864514f5e3Sopenharmony_ci    Register spRegister(SP);
14874514f5e3Sopenharmony_ci    Register pc(X8);
14884514f5e3Sopenharmony_ci    Register prevSpRegister(FP);
14894514f5e3Sopenharmony_ci    Register callTarget(X4);
14904514f5e3Sopenharmony_ci    Register method(X5);
14914514f5e3Sopenharmony_ci    Register temp(X6); // can not be used to store any variable
14924514f5e3Sopenharmony_ci    Register currentSlotRegister(X7);
14934514f5e3Sopenharmony_ci    Register fpRegister(X9);
14944514f5e3Sopenharmony_ci    Register thisRegister(X25);
14954514f5e3Sopenharmony_ci    Register nRegsRegister(X26, W);
14964514f5e3Sopenharmony_ci    Register regsArrayRegister(X27);
14974514f5e3Sopenharmony_ci    Register newSp(X28);
14984514f5e3Sopenharmony_ci    __ Ldr(callTarget, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_METHOD_OFFSET));
14994514f5e3Sopenharmony_ci    __ Ldr(method, MemoryOperand(callTarget, JSFunctionBase::METHOD_OFFSET));
15004514f5e3Sopenharmony_ci    __ PushFpAndLr();
15014514f5e3Sopenharmony_ci    // save fp
15024514f5e3Sopenharmony_ci    __ Mov(fpRegister, spRegister);
15034514f5e3Sopenharmony_ci    __ Mov(currentSlotRegister, spRegister);
15044514f5e3Sopenharmony_ci    // Reserve enough sp space to prevent stack parameters from being covered by cpu profiler.
15054514f5e3Sopenharmony_ci    __ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetStackLimitOffset(false)));
15064514f5e3Sopenharmony_ci    __ Mov(Register(SP), temp);
15074514f5e3Sopenharmony_ci    // push context regs
15084514f5e3Sopenharmony_ci    __ Ldr(nRegsRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_NREGS_OFFSET));
15094514f5e3Sopenharmony_ci    __ Ldr(thisRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_THIS_OFFSET));
15104514f5e3Sopenharmony_ci    __ Ldr(regsArrayRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_REGS_ARRAY_OFFSET));
15114514f5e3Sopenharmony_ci    __ Add(regsArrayRegister, regsArrayRegister, Immediate(TaggedArray::DATA_OFFSET));
15124514f5e3Sopenharmony_ci    PushArgsWithArgv(assembler, glue, nRegsRegister, regsArrayRegister, temp,
15134514f5e3Sopenharmony_ci                     currentSlotRegister, &pushFrameState, &stackOverflow);
15144514f5e3Sopenharmony_ci
15154514f5e3Sopenharmony_ci    __ Bind(&pushFrameState);
15164514f5e3Sopenharmony_ci    __ Mov(newSp, currentSlotRegister);
15174514f5e3Sopenharmony_ci    // push frame state
15184514f5e3Sopenharmony_ci    PushGeneratorFrameState(assembler, prevSpRegister, fpRegister, currentSlotRegister, callTarget, thisRegister,
15194514f5e3Sopenharmony_ci                            method, contextRegister, pc, temp);
15204514f5e3Sopenharmony_ci    __ Align16(currentSlotRegister);
15214514f5e3Sopenharmony_ci    __ Mov(Register(SP), currentSlotRegister);
15224514f5e3Sopenharmony_ci    // call bc stub
15234514f5e3Sopenharmony_ci    CallBCStub(assembler, newSp, glue, callTarget, method, pc, temp);
15244514f5e3Sopenharmony_ci
15254514f5e3Sopenharmony_ci    __ Bind(&stackOverflow);
15264514f5e3Sopenharmony_ci    {
15274514f5e3Sopenharmony_ci        ThrowStackOverflowExceptionAndReturn(assembler, glue, fpRegister, temp);
15284514f5e3Sopenharmony_ci    }
15294514f5e3Sopenharmony_ci}
15304514f5e3Sopenharmony_ci
15314514f5e3Sopenharmony_civoid AsmInterpreterCall::PushCallThis(ExtendedAssembler *assembler,
15324514f5e3Sopenharmony_ci    JSCallMode mode, Label *stackOverflow, FrameTransitionType type)
15334514f5e3Sopenharmony_ci{
15344514f5e3Sopenharmony_ci    Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD);
15354514f5e3Sopenharmony_ci    Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET);
15364514f5e3Sopenharmony_ci    Register thisRegister = __ AvailableRegister2();
15374514f5e3Sopenharmony_ci    Register currentSlotRegister = __ AvailableRegister3();
15384514f5e3Sopenharmony_ci
15394514f5e3Sopenharmony_ci    Label pushVregs;
15404514f5e3Sopenharmony_ci    Label pushNewTarget;
15414514f5e3Sopenharmony_ci    Label pushCallTarget;
15424514f5e3Sopenharmony_ci    bool haveThis = kungfu::AssemblerModule::JSModeHaveThisArg(mode);
15434514f5e3Sopenharmony_ci    bool haveNewTarget = kungfu::AssemblerModule::JSModeHaveNewTargetArg(mode);
15444514f5e3Sopenharmony_ci    if (!haveThis) {
15454514f5e3Sopenharmony_ci        __ Mov(thisRegister, Immediate(JSTaggedValue::VALUE_UNDEFINED));  // default this: undefined
15464514f5e3Sopenharmony_ci    } else {
15474514f5e3Sopenharmony_ci        Register thisArgRegister = GetThisRegsiter(assembler, mode, thisRegister);
15484514f5e3Sopenharmony_ci        if (thisRegister.GetId() != thisArgRegister.GetId()) {
15494514f5e3Sopenharmony_ci            __ Mov(thisRegister, thisArgRegister);
15504514f5e3Sopenharmony_ci        }
15514514f5e3Sopenharmony_ci    }
15524514f5e3Sopenharmony_ci    __ Tst(callFieldRegister, LogicalImmediate::Create(CALL_TYPE_MASK, RegXSize));
15534514f5e3Sopenharmony_ci    __ B(Condition::EQ, &pushVregs);
15544514f5e3Sopenharmony_ci    __ Tbz(callFieldRegister, MethodLiteral::HaveThisBit::START_BIT, &pushNewTarget);
15554514f5e3Sopenharmony_ci    if (!haveThis) {
15564514f5e3Sopenharmony_ci        [[maybe_unused]] TempRegister1Scope scope1(assembler);
15574514f5e3Sopenharmony_ci        Register tempRegister = __ TempRegister1();
15584514f5e3Sopenharmony_ci        __ Mov(tempRegister, Immediate(JSTaggedValue::VALUE_UNDEFINED));
15594514f5e3Sopenharmony_ci        __ Str(tempRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
15604514f5e3Sopenharmony_ci    } else {
15614514f5e3Sopenharmony_ci        __ Str(thisRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
15624514f5e3Sopenharmony_ci    }
15634514f5e3Sopenharmony_ci    __ Bind(&pushNewTarget);
15644514f5e3Sopenharmony_ci    {
15654514f5e3Sopenharmony_ci        __ Tbz(callFieldRegister, MethodLiteral::HaveNewTargetBit::START_BIT, &pushCallTarget);
15664514f5e3Sopenharmony_ci        if (!haveNewTarget) {
15674514f5e3Sopenharmony_ci            [[maybe_unused]] TempRegister1Scope scope1(assembler);
15684514f5e3Sopenharmony_ci            Register newTarget = __ TempRegister1();
15694514f5e3Sopenharmony_ci            __ Mov(newTarget, Immediate(JSTaggedValue::VALUE_UNDEFINED));
15704514f5e3Sopenharmony_ci            __ Str(newTarget, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
15714514f5e3Sopenharmony_ci        } else {
15724514f5e3Sopenharmony_ci            [[maybe_unused]] TempRegister1Scope scope1(assembler);
15734514f5e3Sopenharmony_ci            Register defaultRegister = __ TempRegister1();
15744514f5e3Sopenharmony_ci            Register newTargetRegister = GetNewTargetRegsiter(assembler, mode, defaultRegister);
15754514f5e3Sopenharmony_ci            __ Str(newTargetRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
15764514f5e3Sopenharmony_ci        }
15774514f5e3Sopenharmony_ci    }
15784514f5e3Sopenharmony_ci    __ Bind(&pushCallTarget);
15794514f5e3Sopenharmony_ci    {
15804514f5e3Sopenharmony_ci        __ Tbz(callFieldRegister, MethodLiteral::HaveFuncBit::START_BIT, &pushVregs);
15814514f5e3Sopenharmony_ci        __ Str(callTargetRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
15824514f5e3Sopenharmony_ci    }
15834514f5e3Sopenharmony_ci    __ Bind(&pushVregs);
15844514f5e3Sopenharmony_ci    {
15854514f5e3Sopenharmony_ci        PushVregs(assembler, stackOverflow, type);
15864514f5e3Sopenharmony_ci    }
15874514f5e3Sopenharmony_ci}
15884514f5e3Sopenharmony_ci
15894514f5e3Sopenharmony_civoid AsmInterpreterCall::PushVregs(ExtendedAssembler *assembler,
15904514f5e3Sopenharmony_ci    Label *stackOverflow, FrameTransitionType type)
15914514f5e3Sopenharmony_ci{
15924514f5e3Sopenharmony_ci    Register glue = __ GlueRegister();
15934514f5e3Sopenharmony_ci    Register prevSpRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::SP);
15944514f5e3Sopenharmony_ci    Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET);
15954514f5e3Sopenharmony_ci    Register methodRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::METHOD);
15964514f5e3Sopenharmony_ci    Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD);
15974514f5e3Sopenharmony_ci    Register fpRegister = __ AvailableRegister1();
15984514f5e3Sopenharmony_ci    Register thisRegister = __ AvailableRegister2();
15994514f5e3Sopenharmony_ci    Register currentSlotRegister = __ AvailableRegister3();
16004514f5e3Sopenharmony_ci
16014514f5e3Sopenharmony_ci    Label pushFrameStateAndCall;
16024514f5e3Sopenharmony_ci    [[maybe_unused]] TempRegister1Scope scope1(assembler);
16034514f5e3Sopenharmony_ci    Register tempRegister = __ TempRegister1();
16044514f5e3Sopenharmony_ci    // args register can be reused now.
16054514f5e3Sopenharmony_ci    Register newSpRegister = __ AvailableRegister4();
16064514f5e3Sopenharmony_ci    Register numVregsRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1);
16074514f5e3Sopenharmony_ci    GetNumVregsFromCallField(assembler, callFieldRegister, numVregsRegister);
16084514f5e3Sopenharmony_ci    PushUndefinedWithArgc(assembler, glue, numVregsRegister, tempRegister, currentSlotRegister, &pushFrameStateAndCall,
16094514f5e3Sopenharmony_ci        stackOverflow);
16104514f5e3Sopenharmony_ci    // fall through
16114514f5e3Sopenharmony_ci    __ Bind(&pushFrameStateAndCall);
16124514f5e3Sopenharmony_ci    {
16134514f5e3Sopenharmony_ci        __ Mov(newSpRegister, currentSlotRegister);
16144514f5e3Sopenharmony_ci
16154514f5e3Sopenharmony_ci        [[maybe_unused]] TempRegister2Scope scope2(assembler);
16164514f5e3Sopenharmony_ci        Register pcRegister = __ TempRegister2();
16174514f5e3Sopenharmony_ci        PushFrameState(assembler, prevSpRegister, fpRegister, currentSlotRegister, callTargetRegister, thisRegister,
16184514f5e3Sopenharmony_ci            methodRegister, pcRegister, tempRegister);
16194514f5e3Sopenharmony_ci
16204514f5e3Sopenharmony_ci        __ Align16(currentSlotRegister);
16214514f5e3Sopenharmony_ci        __ Mov(Register(SP), currentSlotRegister);
16224514f5e3Sopenharmony_ci        if (type == FrameTransitionType::OTHER_TO_BASELINE_CHECK ||
16234514f5e3Sopenharmony_ci            type == FrameTransitionType::BASELINE_TO_BASELINE_CHECK) {
16244514f5e3Sopenharmony_ci            // check baselinecode, temp modify TOOD: need to check
16254514f5e3Sopenharmony_ci            Label baselineCodeUndefined;
16264514f5e3Sopenharmony_ci            __ Ldr(tempRegister, MemoryOperand(callTargetRegister, JSFunction::BASELINECODE_OFFSET));
16274514f5e3Sopenharmony_ci            __ Cmp(tempRegister, Immediate(JSTaggedValue::VALUE_UNDEFINED));
16284514f5e3Sopenharmony_ci            __ B(Condition::EQ, &baselineCodeUndefined);
16294514f5e3Sopenharmony_ci
16304514f5e3Sopenharmony_ci            // check is compiling
16314514f5e3Sopenharmony_ci            __ Cmp(tempRegister, Immediate(JSTaggedValue::VALUE_HOLE));
16324514f5e3Sopenharmony_ci            __ B(Condition::EQ, &baselineCodeUndefined);
16334514f5e3Sopenharmony_ci
16344514f5e3Sopenharmony_ci            __ Ldr(tempRegister, MemoryOperand(tempRegister, MachineCode::FUNCADDR_OFFSET));
16354514f5e3Sopenharmony_ci            if (glue != X19) {
16364514f5e3Sopenharmony_ci                __ Mov(X19, glue);
16374514f5e3Sopenharmony_ci            }
16384514f5e3Sopenharmony_ci            if (methodRegister != X21) {
16394514f5e3Sopenharmony_ci                __ Mov(X21, methodRegister);
16404514f5e3Sopenharmony_ci            }
16414514f5e3Sopenharmony_ci            __ Mov(currentSlotRegister, Immediate(BASELINEJIT_PC_FLAG));
16424514f5e3Sopenharmony_ci            // -3: frame type, prevSp, pc
16434514f5e3Sopenharmony_ci            __ Stur(currentSlotRegister, MemoryOperand(newSpRegister, -3 * FRAME_SLOT_SIZE));
16444514f5e3Sopenharmony_ci            __ Mov(Register(X29), newSpRegister);
16454514f5e3Sopenharmony_ci            __ Br(tempRegister);
16464514f5e3Sopenharmony_ci            __ Bind(&baselineCodeUndefined);
16474514f5e3Sopenharmony_ci        }
16484514f5e3Sopenharmony_ci        DispatchCall(assembler, pcRegister, newSpRegister);
16494514f5e3Sopenharmony_ci    }
16504514f5e3Sopenharmony_ci}
16514514f5e3Sopenharmony_ci
16524514f5e3Sopenharmony_ci// Input: X19 - glue
16534514f5e3Sopenharmony_ci//        FP - sp
16544514f5e3Sopenharmony_ci//        X20 - callTarget
16554514f5e3Sopenharmony_ci//        X21 - method
16564514f5e3Sopenharmony_civoid AsmInterpreterCall::DispatchCall(ExtendedAssembler *assembler, Register pcRegister,
16574514f5e3Sopenharmony_ci    Register newSpRegister, Register accRegister)
16584514f5e3Sopenharmony_ci{
16594514f5e3Sopenharmony_ci    Register glueRegister = __ GlueRegister();
16604514f5e3Sopenharmony_ci    Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET);
16614514f5e3Sopenharmony_ci    Register methodRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::METHOD);
16624514f5e3Sopenharmony_ci
16634514f5e3Sopenharmony_ci    if (glueRegister.GetId() != X19) {
16644514f5e3Sopenharmony_ci        __ Mov(Register(X19), glueRegister);
16654514f5e3Sopenharmony_ci    }
16664514f5e3Sopenharmony_ci    __ Ldrh(Register(X24, W), MemoryOperand(methodRegister, Method::LITERAL_INFO_OFFSET));
16674514f5e3Sopenharmony_ci    if (accRegister == INVALID_REG) {
16684514f5e3Sopenharmony_ci        __ Mov(Register(X23), Immediate(JSTaggedValue::VALUE_HOLE));
16694514f5e3Sopenharmony_ci    } else {
16704514f5e3Sopenharmony_ci        ASSERT(accRegister == Register(X23));
16714514f5e3Sopenharmony_ci    }
16724514f5e3Sopenharmony_ci    __ Ldr(Register(X22), MemoryOperand(callTargetRegister, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
16734514f5e3Sopenharmony_ci    __ Ldr(Register(X22), MemoryOperand(Register(X22), ProfileTypeInfoCell::VALUE_OFFSET));
16744514f5e3Sopenharmony_ci    __ Ldr(Register(X21), MemoryOperand(methodRegister, Method::CONSTANT_POOL_OFFSET));
16754514f5e3Sopenharmony_ci    __ Mov(Register(X20), pcRegister);
16764514f5e3Sopenharmony_ci    __ Mov(Register(FP), newSpRegister);
16774514f5e3Sopenharmony_ci
16784514f5e3Sopenharmony_ci    Register bcIndexRegister = __ AvailableRegister1();
16794514f5e3Sopenharmony_ci    Register tempRegister = __ AvailableRegister2();
16804514f5e3Sopenharmony_ci    __ Ldrb(bcIndexRegister.W(), MemoryOperand(pcRegister, 0));
16814514f5e3Sopenharmony_ci    __ Add(tempRegister, glueRegister, Operand(bcIndexRegister.W(), UXTW, FRAME_SLOT_SIZE_LOG2));
16824514f5e3Sopenharmony_ci    __ Ldr(tempRegister, MemoryOperand(tempRegister, JSThread::GlueData::GetBCStubEntriesOffset(false)));
16834514f5e3Sopenharmony_ci    __ Br(tempRegister);
16844514f5e3Sopenharmony_ci}
16854514f5e3Sopenharmony_ci
16864514f5e3Sopenharmony_civoid AsmInterpreterCall::PushFrameState(ExtendedAssembler *assembler, Register prevSp, Register fp,
16874514f5e3Sopenharmony_ci    Register currentSlot, Register callTarget, Register thisObj, Register method, Register pc, Register op)
16884514f5e3Sopenharmony_ci{
16894514f5e3Sopenharmony_ci    __ Mov(op, Immediate(static_cast<int32_t>(FrameType::ASM_INTERPRETER_FRAME)));
16904514f5e3Sopenharmony_ci    __ Stp(prevSp, op, MemoryOperand(currentSlot, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // -2: frame type & prevSp
16914514f5e3Sopenharmony_ci    __ Ldr(pc, MemoryOperand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
16924514f5e3Sopenharmony_ci    __ Stp(fp, pc, MemoryOperand(currentSlot, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // -2: pc & fp
16934514f5e3Sopenharmony_ci    __ Ldr(op, MemoryOperand(callTarget, JSFunction::LEXICAL_ENV_OFFSET));
16944514f5e3Sopenharmony_ci    __ Stp(op, Register(Zero), MemoryOperand(currentSlot,
16954514f5e3Sopenharmony_ci                                             -2 * FRAME_SLOT_SIZE, // -2: jumpSizeAfterCall & env
16964514f5e3Sopenharmony_ci                                             AddrMode::PREINDEX));
16974514f5e3Sopenharmony_ci    __ Mov(op, Immediate(JSTaggedValue::VALUE_HOLE));
16984514f5e3Sopenharmony_ci    __ Stp(thisObj, op, MemoryOperand(currentSlot, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));    // -2: acc & this
16994514f5e3Sopenharmony_ci    __ Str(callTarget, MemoryOperand(currentSlot, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));         // -1: callTarget
17004514f5e3Sopenharmony_ci}
17014514f5e3Sopenharmony_ci
17024514f5e3Sopenharmony_civoid AsmInterpreterCall::GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callField, Register numVregs)
17034514f5e3Sopenharmony_ci{
17044514f5e3Sopenharmony_ci    __ Mov(numVregs, callField);
17054514f5e3Sopenharmony_ci    __ Lsr(numVregs, numVregs, MethodLiteral::NumVregsBits::START_BIT);
17064514f5e3Sopenharmony_ci    __ And(numVregs.W(), numVregs.W(), LogicalImmediate::Create(
17074514f5e3Sopenharmony_ci        MethodLiteral::NumVregsBits::Mask() >> MethodLiteral::NumVregsBits::START_BIT, RegWSize));
17084514f5e3Sopenharmony_ci}
17094514f5e3Sopenharmony_ci
17104514f5e3Sopenharmony_civoid AsmInterpreterCall::GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callField,
17114514f5e3Sopenharmony_ci    Register declaredNumArgs)
17124514f5e3Sopenharmony_ci{
17134514f5e3Sopenharmony_ci    __ Mov(declaredNumArgs, callField);
17144514f5e3Sopenharmony_ci    __ Lsr(declaredNumArgs, declaredNumArgs, MethodLiteral::NumArgsBits::START_BIT);
17154514f5e3Sopenharmony_ci    __ And(declaredNumArgs.W(), declaredNumArgs.W(), LogicalImmediate::Create(
17164514f5e3Sopenharmony_ci        MethodLiteral::NumArgsBits::Mask() >> MethodLiteral::NumArgsBits::START_BIT, RegWSize));
17174514f5e3Sopenharmony_ci}
17184514f5e3Sopenharmony_ci
17194514f5e3Sopenharmony_civoid AsmInterpreterCall::PushAsmInterpEntryFrame(ExtendedAssembler *assembler)
17204514f5e3Sopenharmony_ci{
17214514f5e3Sopenharmony_ci    Register glue = __ GlueRegister();
17224514f5e3Sopenharmony_ci    Register fp(X29);
17234514f5e3Sopenharmony_ci    Register sp(SP);
17244514f5e3Sopenharmony_ci
17254514f5e3Sopenharmony_ci    size_t begin = __ GetCurrentPosition();
17264514f5e3Sopenharmony_ci    if (!assembler->FromInterpreterHandler()) {
17274514f5e3Sopenharmony_ci        __ CalleeSave();
17284514f5e3Sopenharmony_ci    }
17294514f5e3Sopenharmony_ci
17304514f5e3Sopenharmony_ci    [[maybe_unused]] TempRegister1Scope scope1(assembler);
17314514f5e3Sopenharmony_ci    Register prevFrameRegister = __ TempRegister1();
17324514f5e3Sopenharmony_ci    [[maybe_unused]] TempRegister2Scope scope2(assembler);
17334514f5e3Sopenharmony_ci    Register frameTypeRegister = __ TempRegister2();
17344514f5e3Sopenharmony_ci
17354514f5e3Sopenharmony_ci    __ PushFpAndLr();
17364514f5e3Sopenharmony_ci
17374514f5e3Sopenharmony_ci    // prev managed fp is leave frame or nullptr(the first frame)
17384514f5e3Sopenharmony_ci    __ Ldr(prevFrameRegister, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
17394514f5e3Sopenharmony_ci    __ Mov(frameTypeRegister, Immediate(static_cast<int64_t>(FrameType::ASM_INTERPRETER_ENTRY_FRAME)));
17404514f5e3Sopenharmony_ci    // 2 : prevSp & frame type
17414514f5e3Sopenharmony_ci    __ Stp(prevFrameRegister, frameTypeRegister, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
17424514f5e3Sopenharmony_ci    // 2 : pc & glue
17434514f5e3Sopenharmony_ci    __ Stp(glue, Register(Zero), MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));  // pc
17444514f5e3Sopenharmony_ci    if (!assembler->FromInterpreterHandler()) {
17454514f5e3Sopenharmony_ci        size_t end = __ GetCurrentPosition();
17464514f5e3Sopenharmony_ci        if ((end - begin) != FrameCompletionPos::ARM64CppToAsmInterp) {
17474514f5e3Sopenharmony_ci            LOG_COMPILER(FATAL) << (end - begin) << " != " << FrameCompletionPos::ARM64CppToAsmInterp
17484514f5e3Sopenharmony_ci                                << "This frame has been modified, and the offset CppToAsmInterp should be updated too.";
17494514f5e3Sopenharmony_ci        }
17504514f5e3Sopenharmony_ci    }
17514514f5e3Sopenharmony_ci    __ Add(fp, sp, Immediate(4 * FRAME_SLOT_SIZE));  // 4: 32 means skip frame type, prevSp, pc and glue
17524514f5e3Sopenharmony_ci}
17534514f5e3Sopenharmony_ci
17544514f5e3Sopenharmony_civoid AsmInterpreterCall::PopAsmInterpEntryFrame(ExtendedAssembler *assembler)
17554514f5e3Sopenharmony_ci{
17564514f5e3Sopenharmony_ci    Register sp(SP);
17574514f5e3Sopenharmony_ci
17584514f5e3Sopenharmony_ci    [[maybe_unused]] TempRegister1Scope scope1(assembler);
17594514f5e3Sopenharmony_ci    Register prevFrameRegister = __ TempRegister1();
17604514f5e3Sopenharmony_ci    [[maybe_unused]] TempRegister2Scope scope2(assembler);
17614514f5e3Sopenharmony_ci    Register glue = __ TempRegister2();
17624514f5e3Sopenharmony_ci    // 2: glue & pc
17634514f5e3Sopenharmony_ci    __ Ldp(glue, Register(Zero), MemoryOperand(sp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX));
17644514f5e3Sopenharmony_ci    // 2: skip frame type & prev
17654514f5e3Sopenharmony_ci    __ Ldp(prevFrameRegister, Register(Zero), MemoryOperand(sp, 2 * FRAME_SLOT_SIZE, AddrMode::POSTINDEX));
17664514f5e3Sopenharmony_ci    __ Str(prevFrameRegister, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false)));
17674514f5e3Sopenharmony_ci    size_t begin = __ GetCurrentPosition();
17684514f5e3Sopenharmony_ci    __ RestoreFpAndLr();
17694514f5e3Sopenharmony_ci    if (!assembler->FromInterpreterHandler()) {
17704514f5e3Sopenharmony_ci        __ CalleeRestore();
17714514f5e3Sopenharmony_ci        size_t end = __ GetCurrentPosition();
17724514f5e3Sopenharmony_ci        if ((end - begin) != FrameCompletionPos::ARM64AsmInterpToCpp) {
17734514f5e3Sopenharmony_ci            LOG_COMPILER(FATAL) << (end - begin) << " != " << FrameCompletionPos::ARM64AsmInterpToCpp
17744514f5e3Sopenharmony_ci                                << "This frame has been modified, and the offset AsmInterpToCpp should be updated too.";
17754514f5e3Sopenharmony_ci        }
17764514f5e3Sopenharmony_ci    }
17774514f5e3Sopenharmony_ci}
17784514f5e3Sopenharmony_ci
17794514f5e3Sopenharmony_civoid AsmInterpreterCall::PushGeneratorFrameState(ExtendedAssembler *assembler, Register &prevSpRegister,
17804514f5e3Sopenharmony_ci    Register &fpRegister, Register &currentSlotRegister, Register &callTargetRegister, Register &thisRegister,
17814514f5e3Sopenharmony_ci    Register &methodRegister, Register &contextRegister, Register &pcRegister, Register &operatorRegister)
17824514f5e3Sopenharmony_ci{
17834514f5e3Sopenharmony_ci    __ Mov(operatorRegister, Immediate(static_cast<int64_t>(FrameType::ASM_INTERPRETER_FRAME)));
17844514f5e3Sopenharmony_ci    __ Stp(prevSpRegister, operatorRegister,
17854514f5e3Sopenharmony_ci        MemoryOperand(currentSlotRegister, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));  // 2 : frameType and prevSp
17864514f5e3Sopenharmony_ci    __ Ldr(pcRegister, MemoryOperand(methodRegister, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
17874514f5e3Sopenharmony_ci    // offset need 8 align, GENERATOR_NREGS_OFFSET instead of GENERATOR_BC_OFFSET_OFFSET
17884514f5e3Sopenharmony_ci    __ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_NREGS_OFFSET));
17894514f5e3Sopenharmony_ci    // 32: get high 32bit
17904514f5e3Sopenharmony_ci    __ Lsr(operatorRegister, operatorRegister, 32);
17914514f5e3Sopenharmony_ci    __ Add(pcRegister, operatorRegister, pcRegister);
17924514f5e3Sopenharmony_ci    // 2 : pc and fp
17934514f5e3Sopenharmony_ci    __ Stp(fpRegister, pcRegister, MemoryOperand(currentSlotRegister, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
17944514f5e3Sopenharmony_ci    // jumpSizeAfterCall
17954514f5e3Sopenharmony_ci    __ Str(Register(Zero), MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
17964514f5e3Sopenharmony_ci    __ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_LEXICALENV_OFFSET));
17974514f5e3Sopenharmony_ci    // env
17984514f5e3Sopenharmony_ci    __ Str(operatorRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
17994514f5e3Sopenharmony_ci    __ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_ACC_OFFSET));
18004514f5e3Sopenharmony_ci    // acc
18014514f5e3Sopenharmony_ci    __ Str(operatorRegister, MemoryOperand(currentSlotRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX));
18024514f5e3Sopenharmony_ci    __ Stp(callTargetRegister, thisRegister,
18034514f5e3Sopenharmony_ci        MemoryOperand(currentSlotRegister, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));  // 2 : acc and callTarget
18044514f5e3Sopenharmony_ci}
18054514f5e3Sopenharmony_ci
18064514f5e3Sopenharmony_civoid AsmInterpreterCall::CallBCStub(ExtendedAssembler *assembler, Register &newSp, Register &glue,
18074514f5e3Sopenharmony_ci    Register &callTarget, Register &method, Register &pc, Register &temp)
18084514f5e3Sopenharmony_ci{
18094514f5e3Sopenharmony_ci    // prepare call entry
18104514f5e3Sopenharmony_ci    __ Mov(Register(X19), glue);    // X19 - glue
18114514f5e3Sopenharmony_ci    __ Mov(Register(FP), newSp);    // FP - sp
18124514f5e3Sopenharmony_ci    __ Mov(Register(X20), pc);      // X20 - pc
18134514f5e3Sopenharmony_ci    __ Ldr(Register(X21), MemoryOperand(method, Method::CONSTANT_POOL_OFFSET));   // X21 - constantpool
18144514f5e3Sopenharmony_ci    __ Ldr(Register(X22), MemoryOperand(callTarget, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
18154514f5e3Sopenharmony_ci    __ Ldr(Register(X22), MemoryOperand(Register(X22), ProfileTypeInfoCell::VALUE_OFFSET));  // X22 - profileTypeInfo
18164514f5e3Sopenharmony_ci    __ Mov(Register(X23), Immediate(JSTaggedValue::Hole().GetRawData()));                   // X23 - acc
18174514f5e3Sopenharmony_ci    __ Ldr(Register(X24), MemoryOperand(method, Method::LITERAL_INFO_OFFSET)); // X24 - hotnessCounter
18184514f5e3Sopenharmony_ci
18194514f5e3Sopenharmony_ci    // call the first bytecode handler
18204514f5e3Sopenharmony_ci    __ Ldrb(temp.W(), MemoryOperand(pc, 0));
18214514f5e3Sopenharmony_ci    // 3 : 3 means *8
18224514f5e3Sopenharmony_ci    __ Add(temp, glue, Operand(temp.W(), UXTW, FRAME_SLOT_SIZE_LOG2));
18234514f5e3Sopenharmony_ci    __ Ldr(temp, MemoryOperand(temp, JSThread::GlueData::GetBCStubEntriesOffset(false)));
18244514f5e3Sopenharmony_ci    __ Br(temp);
18254514f5e3Sopenharmony_ci}
18264514f5e3Sopenharmony_ci
18274514f5e3Sopenharmony_civoid AsmInterpreterCall::CallNativeEntry(ExtendedAssembler *assembler)
18284514f5e3Sopenharmony_ci{
18294514f5e3Sopenharmony_ci    Label callFastBuiltin;
18304514f5e3Sopenharmony_ci    Label callNativeBuiltin;
18314514f5e3Sopenharmony_ci    Register glue(X0);
18324514f5e3Sopenharmony_ci    Register argv(X5);
18334514f5e3Sopenharmony_ci    Register method(X2);
18344514f5e3Sopenharmony_ci    Register function(X1);
18354514f5e3Sopenharmony_ci    Register nativeCode(X7);
18364514f5e3Sopenharmony_ci    Register temp(X9);
18374514f5e3Sopenharmony_ci    Register callFieldRegister(X3);
18384514f5e3Sopenharmony_ci    // get native pointer
18394514f5e3Sopenharmony_ci    __ Ldr(nativeCode, MemoryOperand(method, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
18404514f5e3Sopenharmony_ci    __ Tbnz(callFieldRegister, MethodLiteral::IsFastBuiltinBit::START_BIT, &callFastBuiltin);
18414514f5e3Sopenharmony_ci
18424514f5e3Sopenharmony_ci    __ Bind(&callNativeBuiltin);
18434514f5e3Sopenharmony_ci    Register sp(SP);
18444514f5e3Sopenharmony_ci    // 2: function & align
18454514f5e3Sopenharmony_ci    __ Stp(function, Register(Zero), MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX));
18464514f5e3Sopenharmony_ci    // 2: skip argc & thread
18474514f5e3Sopenharmony_ci    __ Sub(sp, sp, Immediate(2 * FRAME_SLOT_SIZE));
18484514f5e3Sopenharmony_ci    PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_ENTRY_FRAME, temp, argv);
18494514f5e3Sopenharmony_ci    __ Mov(temp, argv);
18504514f5e3Sopenharmony_ci    __ Sub(Register(X0), temp, Immediate(2 * FRAME_SLOT_SIZE));  // 2: skip argc & thread
18514514f5e3Sopenharmony_ci    CallNativeInternal(assembler, nativeCode);
18524514f5e3Sopenharmony_ci
18534514f5e3Sopenharmony_ci    // 4: skip function
18544514f5e3Sopenharmony_ci    __ Add(sp, sp, Immediate(4 * FRAME_SLOT_SIZE));
18554514f5e3Sopenharmony_ci    __ Ret();
18564514f5e3Sopenharmony_ci
18574514f5e3Sopenharmony_ci    __ Bind(&callFastBuiltin);
18584514f5e3Sopenharmony_ci    CallFastBuiltin(assembler, &callNativeBuiltin);
18594514f5e3Sopenharmony_ci}
18604514f5e3Sopenharmony_ci
18614514f5e3Sopenharmony_civoid AsmInterpreterCall::CallFastBuiltin(ExtendedAssembler *assembler, Label *callNativeBuiltin)
18624514f5e3Sopenharmony_ci{
18634514f5e3Sopenharmony_ci    Label lCall1;
18644514f5e3Sopenharmony_ci    Label lCall2;
18654514f5e3Sopenharmony_ci    Label lCall3;
18664514f5e3Sopenharmony_ci    Label callEntry;
18674514f5e3Sopenharmony_ci    Register sp(SP);
18684514f5e3Sopenharmony_ci    Register glue(X0);
18694514f5e3Sopenharmony_ci    Register function(X1);
18704514f5e3Sopenharmony_ci    Register method(X2);
18714514f5e3Sopenharmony_ci    Register argc(X4);
18724514f5e3Sopenharmony_ci    Register argv(X5);
18734514f5e3Sopenharmony_ci    Register nativeCode(X7);
18744514f5e3Sopenharmony_ci
18754514f5e3Sopenharmony_ci    Register builtinId = __ AvailableRegister1();
18764514f5e3Sopenharmony_ci    Register temp = __ AvailableRegister2();
18774514f5e3Sopenharmony_ci    // get builtinid
18784514f5e3Sopenharmony_ci    __ Ldr(builtinId, MemoryOperand(method, Method::EXTRA_LITERAL_INFO_OFFSET));  // get extra literal
18794514f5e3Sopenharmony_ci    __ And(builtinId.W(), builtinId.W(), LogicalImmediate::Create(0xff, RegWSize));
18804514f5e3Sopenharmony_ci    __ Cmp(builtinId.W(), Immediate(kungfu::BuiltinsStubCSigns::BUILTINS_CONSTRUCTOR_STUB_FIRST));
18814514f5e3Sopenharmony_ci    __ B(Condition::GE, callNativeBuiltin);
18824514f5e3Sopenharmony_ci
18834514f5e3Sopenharmony_ci    __ Cmp(argc, Immediate(3)); // 3: number of args
18844514f5e3Sopenharmony_ci    __ B(Condition::HI, callNativeBuiltin);
18854514f5e3Sopenharmony_ci
18864514f5e3Sopenharmony_ci    // get builtin func addr
18874514f5e3Sopenharmony_ci    __ Add(builtinId, glue, Operand(builtinId.W(), UXTW, FRAME_SLOT_SIZE_LOG2));
18884514f5e3Sopenharmony_ci    __ Ldr(builtinId, MemoryOperand(builtinId, JSThread::GlueData::GetBuiltinsStubEntriesOffset(false)));
18894514f5e3Sopenharmony_ci    // create frame
18904514f5e3Sopenharmony_ci    PushAsmBridgeFrame(assembler);
18914514f5e3Sopenharmony_ci    __ Mov(temp, function);
18924514f5e3Sopenharmony_ci    __ Mov(X1, nativeCode);
18934514f5e3Sopenharmony_ci    __ Mov(X2, temp);
18944514f5e3Sopenharmony_ci    __ Mov(temp, argv);
18954514f5e3Sopenharmony_ci    __ Mov(X5, argc);
18964514f5e3Sopenharmony_ci    __ Ldr(X3, MemoryOperand(temp, FRAME_SLOT_SIZE));
18974514f5e3Sopenharmony_ci    __ Ldr(X4, MemoryOperand(temp, DOUBLE_SLOT_SIZE));
18984514f5e3Sopenharmony_ci
18994514f5e3Sopenharmony_ci    __ Cmp(Register(X5), Immediate(0));
19004514f5e3Sopenharmony_ci    __ B(Condition::NE, &lCall1);
19014514f5e3Sopenharmony_ci    __ Mov(Register(X6), Immediate(JSTaggedValue::VALUE_UNDEFINED));
19024514f5e3Sopenharmony_ci    __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED));
19034514f5e3Sopenharmony_ci    __ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX));
19044514f5e3Sopenharmony_ci    __ B(&callEntry);
19054514f5e3Sopenharmony_ci
19064514f5e3Sopenharmony_ci    __ Bind(&lCall1);
19074514f5e3Sopenharmony_ci    {
19084514f5e3Sopenharmony_ci        __ Cmp(Register(X5), Immediate(1));
19094514f5e3Sopenharmony_ci        __ B(Condition::NE, &lCall2);
19104514f5e3Sopenharmony_ci        __ Ldr(Register(X6), MemoryOperand(temp, TRIPLE_SLOT_SIZE));
19114514f5e3Sopenharmony_ci        __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED));  // reset x7
19124514f5e3Sopenharmony_ci        __ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX));
19134514f5e3Sopenharmony_ci        __ B(&callEntry);
19144514f5e3Sopenharmony_ci    }
19154514f5e3Sopenharmony_ci
19164514f5e3Sopenharmony_ci    __ Bind(&lCall2);
19174514f5e3Sopenharmony_ci    {
19184514f5e3Sopenharmony_ci        __ Cmp(Register(X5), Immediate(2)); // 2: number of args
19194514f5e3Sopenharmony_ci        __ B(Condition::NE, &lCall3);
19204514f5e3Sopenharmony_ci        __ Mov(Register(X7), Immediate(JSTaggedValue::VALUE_UNDEFINED));
19214514f5e3Sopenharmony_ci        __ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX));
19224514f5e3Sopenharmony_ci        __ Ldp(Register(X6), Register(X7), MemoryOperand(temp, TRIPLE_SLOT_SIZE));
19234514f5e3Sopenharmony_ci        __ B(&callEntry);
19244514f5e3Sopenharmony_ci    }
19254514f5e3Sopenharmony_ci
19264514f5e3Sopenharmony_ci    __ Bind(&lCall3);
19274514f5e3Sopenharmony_ci    {
19284514f5e3Sopenharmony_ci        __ Ldr(Register(X7), MemoryOperand(temp, QUINTUPLE_SLOT_SIZE));
19294514f5e3Sopenharmony_ci        __ Stp(Register(X7), Register(X7), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, PREINDEX));
19304514f5e3Sopenharmony_ci        __ Ldp(Register(X6), Register(X7), MemoryOperand(temp, TRIPLE_SLOT_SIZE));  // get arg0 arg1
19314514f5e3Sopenharmony_ci        __ B(&callEntry);
19324514f5e3Sopenharmony_ci    }
19334514f5e3Sopenharmony_ci
19344514f5e3Sopenharmony_ci    __ Bind(&callEntry);
19354514f5e3Sopenharmony_ci    {
19364514f5e3Sopenharmony_ci        __ Blr(builtinId);
19374514f5e3Sopenharmony_ci        __ Add(sp, sp, Immediate(DOUBLE_SLOT_SIZE));
19384514f5e3Sopenharmony_ci    }
19394514f5e3Sopenharmony_ci    PopAsmBridgeFrame(assembler);
19404514f5e3Sopenharmony_ci    __ Ret();
19414514f5e3Sopenharmony_ci}
19424514f5e3Sopenharmony_ci
19434514f5e3Sopenharmony_civoid AsmInterpreterCall::ThrowStackOverflowExceptionAndReturn(ExtendedAssembler *assembler, Register glue,
19444514f5e3Sopenharmony_ci    Register fp, Register op)
19454514f5e3Sopenharmony_ci{
19464514f5e3Sopenharmony_ci    if (fp != Register(SP)) {
19474514f5e3Sopenharmony_ci        __ Mov(Register(SP), fp);
19484514f5e3Sopenharmony_ci    }
19494514f5e3Sopenharmony_ci    __ Mov(op, Immediate(kungfu::RuntimeStubCSigns::ID_ThrowStackOverflowException));
19504514f5e3Sopenharmony_ci    // 3 : 3 means *8
19514514f5e3Sopenharmony_ci    __ Add(op, glue, Operand(op, LSL, 3));
19524514f5e3Sopenharmony_ci    __ Ldr(op, MemoryOperand(op, JSThread::GlueData::GetRTStubEntriesOffset(false)));
19534514f5e3Sopenharmony_ci    if (glue.GetId() != X0) {
19544514f5e3Sopenharmony_ci        __ Mov(Register(X0), glue);
19554514f5e3Sopenharmony_ci    }
19564514f5e3Sopenharmony_ci    __ Blr(op);
19574514f5e3Sopenharmony_ci    __ RestoreFpAndLr();
19584514f5e3Sopenharmony_ci    __ Ret();
19594514f5e3Sopenharmony_ci}
19604514f5e3Sopenharmony_ci#undef __
19614514f5e3Sopenharmony_ci}  // panda::ecmascript::aarch64