* Copyright (c) 2022-2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/compiler/trampoline/x64/common_call.h"
#include "ecmascript/runtime_call_id.h"
namespace panda::ecmascript::x64 {
#define __ assembler->
void CommonCall::CopyArgumentWithArgV(ExtendedAssembler *assembler, Register argc, Register argV)
{
Label loopBeginning;
Register arg = __ AvailableRegister1();
__ Bind(&loopBeginning);
__ Movq(Operand(argV, argc, Scale::Times8, -FRAME_SLOT_SIZE), arg);
__ Pushq(arg);
__ Subq(1, argc);
__ Ja(&loopBeginning);
}
void CommonCall::PushAsmInterpBridgeFrame(ExtendedAssembler *assembler)
{
__ Pushq(static_cast<int64_t>(FrameType::ASM_INTERPRETER_BRIDGE_FRAME));
__ Pushq(rbp);
__ Pushq(0);
__ Leaq(Operand(rsp, 24), rbp);
__ PushAlignBytes();
if (!assembler->FromInterpreterHandler()) {
__ PushCppCalleeSaveRegisters();
}
}
void CommonCall::GetArgvAtStack(ExtendedAssembler *assembler)
{
Register r13 = __ CppJSCallAvailableRegister1();
Register r14 = __ CppJSCallAvailableRegister2();
__ Movq(Operand(rbp, FRAME_SLOT_SIZE), r13);
__ Movq(Operand(rbp, 2 * FRAME_SLOT_SIZE), r14);
}
void CommonCall::PopAsmInterpBridgeFrame(ExtendedAssembler *assembler)
{
if (!assembler->FromInterpreterHandler()) {
#ifdef ENABLE_CMC_IR_FIX_REGISTER
__ PopCppCalleeSaveNoReservedRegisters();
#else
__ PopCppCalleeSaveRegisters();
#endif
}
__ PopAlignBytes();
__ Addq(8, rsp);
__ Popq(rbp);
__ Addq(8, rsp);
}
void CommonCall::PushUndefinedWithArgc(ExtendedAssembler *assembler, Register argc)
{
Label loopBeginning;
__ Bind(&loopBeginning);
__ Pushq(JSTaggedValue::Undefined().GetRawData());
__ Subq(1, argc);
__ Ja(&loopBeginning);
}
void CommonCall::PushArgsWithArgvAndCheckStack(ExtendedAssembler *assembler, Register glue, Register argc,
Register argv, Register op1, Register op2, Label *stackOverflow)
{
ASSERT(stackOverflow != nullptr);
StackOverflowCheck(assembler, glue, argc, op1, op2, stackOverflow);
Register opArgc = argc;
Register op = op1;
if (op1 != op2) {
opArgc = op2;
__ Movq(argc, opArgc);
}
Label loopBeginning;
__ Bind(&loopBeginning);
__ Movq(Operand(argv, opArgc, Times8, -8), op);
__ Pushq(op);
__ Subq(1, opArgc);
__ Ja(&loopBeginning);
}
void CommonCall::StackOverflowCheck(ExtendedAssembler *assembler, Register glue, Register numArgs, Register op1,
Register op2, Label *stackOverflow)
{
Register temp1 = op1;
Register temp2 = op2;
if (op1 == op2) {
__ Pushq(glue);
temp2 = glue;
}
__ Movq(Operand(glue, JSThread::GlueData::GetStackLimitOffset(false)), temp1);
__ Movq(rsp, temp2);
__ Subq(temp1, temp2);
__ Movl(numArgs, temp1);
__ Shlq(3, temp1);
__ Cmpq(temp1, temp2);
if (op1 == op2) {
__ Popq(glue);
}
__ Jle(stackOverflow);
}
void CommonCall::PushAsmBridgeFrame(ExtendedAssembler *assembler)
{
__ Pushq(rbp);
__ Pushq(static_cast<int32_t>(FrameType::ASM_BRIDGE_FRAME));
__ Leaq(Operand(rsp, FRAME_SLOT_SIZE), rbp);
}
void CommonCall::PopAsmBridgeFrame(ExtendedAssembler *assembler)
{
__ Addq(FRAME_SLOT_SIZE, rsp);
__ Popq(rbp);
}
#undef __
}