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