14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/compiler/assembler/x64/macro_assembler_x64.h"
174514f5e3Sopenharmony_ci#include "ecmascript/js_function.h"
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
204514f5e3Sopenharmony_ciusing namespace panda::ecmascript;
214514f5e3Sopenharmony_ci
224514f5e3Sopenharmony_civoid MacroAssemblerX64::Move(const StackSlotOperand &dstStackSlot, Immediate value)
234514f5e3Sopenharmony_ci{
244514f5e3Sopenharmony_ci    x64::Register baseReg = (dstStackSlot.IsFrameBase()) ? x64::rbp : x64::rsp;
254514f5e3Sopenharmony_ci    x64::Operand dstOpnd(baseReg, dstStackSlot.GetOffset());
264514f5e3Sopenharmony_ci    assembler.Movabs(value.GetValue(), LOCAL_SCOPE_REGISTER);
274514f5e3Sopenharmony_ci    assembler.Movq(LOCAL_SCOPE_REGISTER, dstOpnd);
284514f5e3Sopenharmony_ci}
294514f5e3Sopenharmony_ci
304514f5e3Sopenharmony_civoid MacroAssemblerX64::Move(const StackSlotOperand &dstStackSlot,
314514f5e3Sopenharmony_ci                             const StackSlotOperand &srcStackSlot)
324514f5e3Sopenharmony_ci{
334514f5e3Sopenharmony_ci    x64::Register dstBaseReg = (dstStackSlot.IsFrameBase()) ? x64::rbp : x64::rsp;
344514f5e3Sopenharmony_ci    x64::Register srcBaseReg = (srcStackSlot.IsFrameBase()) ? x64::rbp : x64::rsp;
354514f5e3Sopenharmony_ci    x64::Operand srcOpnd(srcBaseReg, srcStackSlot.GetOffset());
364514f5e3Sopenharmony_ci    x64::Operand dstOpnd(dstBaseReg, dstStackSlot.GetOffset());
374514f5e3Sopenharmony_ci    assembler.Movq(srcOpnd, LOCAL_SCOPE_REGISTER);
384514f5e3Sopenharmony_ci    assembler.Movq(LOCAL_SCOPE_REGISTER, dstOpnd);
394514f5e3Sopenharmony_ci}
404514f5e3Sopenharmony_ci
414514f5e3Sopenharmony_civoid MacroAssemblerX64::Cmp(const StackSlotOperand &stackSlot, Immediate value)
424514f5e3Sopenharmony_ci{
434514f5e3Sopenharmony_ci    x64::Register baseReg = (stackSlot.IsFrameBase()) ? x64::rbp : x64::rsp;
444514f5e3Sopenharmony_ci    x64::Operand opnd(baseReg, stackSlot.GetOffset());
454514f5e3Sopenharmony_ci    assembler.Movq(opnd, LOCAL_SCOPE_REGISTER);
464514f5e3Sopenharmony_ci    assembler.Cmp(x64::Immediate(value.GetValue()), LOCAL_SCOPE_REGISTER);
474514f5e3Sopenharmony_ci}
484514f5e3Sopenharmony_ci
494514f5e3Sopenharmony_civoid MacroAssemblerX64::Bind(JumpLabel &label)
504514f5e3Sopenharmony_ci{
514514f5e3Sopenharmony_ci    assembler.Bind(&label);
524514f5e3Sopenharmony_ci}
534514f5e3Sopenharmony_ci
544514f5e3Sopenharmony_civoid MacroAssemblerX64::Jz(JumpLabel &label)
554514f5e3Sopenharmony_ci{
564514f5e3Sopenharmony_ci    assembler.Jz(&label);
574514f5e3Sopenharmony_ci}
584514f5e3Sopenharmony_ci
594514f5e3Sopenharmony_civoid MacroAssemblerX64::Jnz(JumpLabel &label)
604514f5e3Sopenharmony_ci{
614514f5e3Sopenharmony_ci    assembler.Jnz(&label);
624514f5e3Sopenharmony_ci}
634514f5e3Sopenharmony_ci
644514f5e3Sopenharmony_civoid MacroAssemblerX64::Jump(JumpLabel &label)
654514f5e3Sopenharmony_ci{
664514f5e3Sopenharmony_ci    assembler.Jmp(&label);
674514f5e3Sopenharmony_ci}
684514f5e3Sopenharmony_ci
694514f5e3Sopenharmony_civoid MacroAssemblerX64::SaveReturnRegister(const StackSlotOperand &dstStackSlot)
704514f5e3Sopenharmony_ci{
714514f5e3Sopenharmony_ci    x64::Register dstBaseReg = (dstStackSlot.IsFrameBase()) ? x64::rbp : x64::rsp;
724514f5e3Sopenharmony_ci    x64::Operand dstOpnd(dstBaseReg, dstStackSlot.GetOffset());
734514f5e3Sopenharmony_ci    assembler.Movq(RETURN_REGISTER, dstOpnd);
744514f5e3Sopenharmony_ci}
754514f5e3Sopenharmony_ci
764514f5e3Sopenharmony_civoid MacroAssemblerX64::MovParameterIntoParamReg(MacroParameter param, x64::Register paramReg)
774514f5e3Sopenharmony_ci{
784514f5e3Sopenharmony_ci    if (std::holds_alternative<BaselineSpecialParameter>(param)) {
794514f5e3Sopenharmony_ci        auto specialParam = std::get<BaselineSpecialParameter>(param);
804514f5e3Sopenharmony_ci        switch (specialParam) {
814514f5e3Sopenharmony_ci            case BaselineSpecialParameter::GLUE: {
824514f5e3Sopenharmony_ci                assembler.Movq(GLUE_REGISTER, paramReg);
834514f5e3Sopenharmony_ci                break;
844514f5e3Sopenharmony_ci            }
854514f5e3Sopenharmony_ci            case BaselineSpecialParameter::PROFILE_TYPE_INFO: {
864514f5e3Sopenharmony_ci                assembler.Movq(x64::Operand(x64::rbp, FUNCTION_OFFSET_FROM_SP), LOCAL_SCOPE_REGISTER);
874514f5e3Sopenharmony_ci                assembler.Movq(
884514f5e3Sopenharmony_ci                    x64::Operand(LOCAL_SCOPE_REGISTER, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET),
894514f5e3Sopenharmony_ci                    LOCAL_SCOPE_REGISTER);
904514f5e3Sopenharmony_ci                assembler.Movq(x64::Operand(LOCAL_SCOPE_REGISTER, ProfileTypeInfoCell::VALUE_OFFSET), paramReg);
914514f5e3Sopenharmony_ci                break;
924514f5e3Sopenharmony_ci            }
934514f5e3Sopenharmony_ci            case BaselineSpecialParameter::SP: {
944514f5e3Sopenharmony_ci                assembler.Movq(x64::rbp, paramReg);
954514f5e3Sopenharmony_ci                break;
964514f5e3Sopenharmony_ci            }
974514f5e3Sopenharmony_ci            case BaselineSpecialParameter::HOTNESS_COUNTER: {
984514f5e3Sopenharmony_ci                assembler.Movq(x64::Operand(x64::rbp, FUNCTION_OFFSET_FROM_SP), LOCAL_SCOPE_REGISTER);
994514f5e3Sopenharmony_ci                assembler.Movq(
1004514f5e3Sopenharmony_ci                    x64::Operand(LOCAL_SCOPE_REGISTER, JSFunctionBase::METHOD_OFFSET), LOCAL_SCOPE_REGISTER);
1014514f5e3Sopenharmony_ci                assembler.Movzwq(x64::Operand(LOCAL_SCOPE_REGISTER, Method::LITERAL_INFO_OFFSET), paramReg);
1024514f5e3Sopenharmony_ci                break;
1034514f5e3Sopenharmony_ci            }
1044514f5e3Sopenharmony_ci            default: {
1054514f5e3Sopenharmony_ci                std::cout << "not supported BaselineSpecialParameter currently" << std::endl;
1064514f5e3Sopenharmony_ci                std::abort();
1074514f5e3Sopenharmony_ci            }
1084514f5e3Sopenharmony_ci        }
1094514f5e3Sopenharmony_ci        return;
1104514f5e3Sopenharmony_ci    }
1114514f5e3Sopenharmony_ci    if (std::holds_alternative<int8_t>(param)) {
1124514f5e3Sopenharmony_ci        int16_t num = std::get<int8_t>(param);
1134514f5e3Sopenharmony_ci        assembler.Movq(panda::ecmascript::x64::Immediate(static_cast<int32_t>(num)), paramReg);
1144514f5e3Sopenharmony_ci        return;
1154514f5e3Sopenharmony_ci    }
1164514f5e3Sopenharmony_ci    if (std::holds_alternative<int16_t>(param)) {
1174514f5e3Sopenharmony_ci        int16_t num = std::get<int16_t>(param);
1184514f5e3Sopenharmony_ci        assembler.Movq(panda::ecmascript::x64::Immediate(static_cast<int32_t>(num)), paramReg);
1194514f5e3Sopenharmony_ci        return;
1204514f5e3Sopenharmony_ci    }
1214514f5e3Sopenharmony_ci    if (std::holds_alternative<int32_t>(param)) {
1224514f5e3Sopenharmony_ci        int32_t num = std::get<int32_t>(param);
1234514f5e3Sopenharmony_ci        assembler.Movq(panda::ecmascript::x64::Immediate(num), paramReg);
1244514f5e3Sopenharmony_ci        return;
1254514f5e3Sopenharmony_ci    }
1264514f5e3Sopenharmony_ci    if (std::holds_alternative<int64_t>(param)) {
1274514f5e3Sopenharmony_ci        int64_t num = std::get<int64_t>(param);
1284514f5e3Sopenharmony_ci        assembler.Movabs(num, paramReg);
1294514f5e3Sopenharmony_ci        return;
1304514f5e3Sopenharmony_ci    }
1314514f5e3Sopenharmony_ci    if (std::holds_alternative<StackSlotOperand>(param)) {
1324514f5e3Sopenharmony_ci        StackSlotOperand stackSlotOpnd = std::get<StackSlotOperand>(param);
1334514f5e3Sopenharmony_ci        x64::Register dstBaseReg = (stackSlotOpnd.IsFrameBase()) ? x64::rbp : x64::rsp;
1344514f5e3Sopenharmony_ci        x64::Operand paramOpnd(dstBaseReg, stackSlotOpnd.GetOffset());
1354514f5e3Sopenharmony_ci        assembler.Movq(paramOpnd, paramReg);
1364514f5e3Sopenharmony_ci        return;
1374514f5e3Sopenharmony_ci    }
1384514f5e3Sopenharmony_ci    std::cout << "not supported other type of baseline parameters currently" << std::endl;
1394514f5e3Sopenharmony_ci    std::abort();
1404514f5e3Sopenharmony_ci}
1414514f5e3Sopenharmony_ci
1424514f5e3Sopenharmony_civoid MacroAssemblerX64::CallBuiltin(Address funcAddress,
1434514f5e3Sopenharmony_ci                                    const std::vector<MacroParameter> &parameters)
1444514f5e3Sopenharmony_ci{
1454514f5e3Sopenharmony_ci    for (size_t i = 0; i < parameters.size(); ++i) {
1464514f5e3Sopenharmony_ci        auto param = parameters[i];
1474514f5e3Sopenharmony_ci        if (i == PARAM_REGISTER_COUNT) {
1484514f5e3Sopenharmony_ci            std::cout << "should not pass parameters on the stack" << std::endl;
1494514f5e3Sopenharmony_ci            std::abort();
1504514f5e3Sopenharmony_ci        }
1514514f5e3Sopenharmony_ci        MovParameterIntoParamReg(param, registerParamVec[i]);
1524514f5e3Sopenharmony_ci    }
1534514f5e3Sopenharmony_ci    assembler.Movabs(static_cast<uint64_t>(funcAddress), LOCAL_SCOPE_REGISTER);
1544514f5e3Sopenharmony_ci    assembler.Callq(LOCAL_SCOPE_REGISTER);
1554514f5e3Sopenharmony_ci}
1564514f5e3Sopenharmony_ci
1574514f5e3Sopenharmony_ci}  // namespace panda::ecmascript::kungfu
158