1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "ecmascript/compiler/baseline/baseline_assembler.h"
17#include "ecmascript/compiler/assembler/x64/macro_assembler_x64.h"
18#include "ecmascript/compiler/assembler/aarch64/macro_assembler_aarch64.h"
19
20namespace panda::ecmascript::kungfu {
21using namespace panda::ecmascript;
22BaselineAssembler::BaselineAssembler(const std::string &tripleStr) : stackOffsetDescriptor(0)
23{
24    NativeAreaAllocator allocator;
25    Chunk chunk(&allocator);
26    if (tripleStr.compare(TARGET_X64) == 0) {
27        macroAssembler = new MacroAssemblerX64();
28    } else if (tripleStr.compare(TARGET_AARCH64) == 0) {
29        macroAssembler = new MacroAssemblerAArch64();
30        static_cast<MacroAssemblerAArch64*>(macroAssembler)->SetBaselineFlag();
31    } else {
32        LOG_ECMA(FATAL) << "this branch is unreachable";
33        UNREACHABLE();
34    }
35};
36
37void BaselineAssembler::Move(VirtualRegister interpreterDestReg, Immediate value)
38{
39    StackSlotOperand stackSlotOperand(StackSlotOperand::BaseRegister::FRAME_REGISTER,
40        stackOffsetDescriptor.GetVregOffset(interpreterDestReg));
41
42    macroAssembler->Move(stackSlotOperand, value);
43}
44
45void BaselineAssembler::Move(SpecialRegister destReg, Immediate value)
46{
47    StackSlotOperand stackSlotOperand(StackSlotOperand::BaseRegister::FRAME_REGISTER,
48        stackOffsetDescriptor.GetSpecialRegisterOffset(destReg));
49
50    macroAssembler->Move(stackSlotOperand, value);
51}
52
53void BaselineAssembler::Move(SpecialRegister destReg, SpecialRegister srcReg)
54{
55    StackSlotOperand srcStackSlotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
56        stackOffsetDescriptor.GetSpecialRegisterOffset(srcReg));
57
58    StackSlotOperand dstStackSlotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
59        stackOffsetDescriptor.GetSpecialRegisterOffset(destReg));
60    macroAssembler->Move(dstStackSlotOpnd, srcStackSlotOpnd);
61}
62
63void BaselineAssembler::Move(VirtualRegister interpreterDestReg, VirtualRegister interpreterSrcReg)
64{
65    StackSlotOperand srcStackSlotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
66        stackOffsetDescriptor.GetVregOffset(interpreterSrcReg));
67
68    StackSlotOperand dstStackSlotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
69        stackOffsetDescriptor.GetVregOffset(interpreterDestReg));
70
71    macroAssembler->Move(dstStackSlotOpnd, srcStackSlotOpnd);
72}
73
74void BaselineAssembler::Move(SpecialRegister destReg, VirtualRegister interpreterSrcReg)
75{
76    StackSlotOperand srcStackSlotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
77        stackOffsetDescriptor.GetVregOffset(interpreterSrcReg));
78
79    StackSlotOperand dstStackSlotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
80        stackOffsetDescriptor.GetSpecialRegisterOffset(destReg));
81
82    macroAssembler->Move(dstStackSlotOpnd, srcStackSlotOpnd);
83}
84
85void BaselineAssembler::Move(VirtualRegister interpreterDestReg, SpecialRegister srcReg)
86{
87    StackSlotOperand srcStackSlotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
88        stackOffsetDescriptor.GetSpecialRegisterOffset(srcReg));
89
90    StackSlotOperand dstStackSlotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
91        stackOffsetDescriptor.GetVregOffset(interpreterDestReg));
92
93    macroAssembler->Move(dstStackSlotOpnd, srcStackSlotOpnd);
94}
95
96void BaselineAssembler::Cmp(SpecialRegister reg, Immediate value)
97{
98    StackSlotOperand stackSlotOperand(StackSlotOperand::BaseRegister::FRAME_REGISTER,
99        stackOffsetDescriptor.GetSpecialRegisterOffset(reg));
100
101    macroAssembler->Cmp(stackSlotOperand, value);
102}
103
104void BaselineAssembler::SaveResultIntoAcc()
105{
106    StackSlotOperand dstStackSlotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
107        stackOffsetDescriptor.GetSpecialRegisterOffset(SpecialRegister::ACC_REGISTER));
108
109    macroAssembler->SaveReturnRegister(dstStackSlotOpnd);
110}
111
112void BaselineAssembler::CallBuiltin(Address funcAddress,
113                                    const std::vector<BaselineParameter> &parameters)
114{
115    std::vector<MacroParameter> macroParameters;
116    for (const auto &param : parameters) {
117        if (std::holds_alternative<BaselineSpecialParameter>(param)) {
118            switch (std::get<BaselineSpecialParameter>(param)) {
119                case BaselineSpecialParameter::ACC: {
120                    StackSlotOperand slotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
121                        stackOffsetDescriptor.GetSpecialRegisterOffset(SpecialRegister::ACC_REGISTER));
122                    macroParameters.emplace_back(slotOpnd);
123                    break;
124                }
125                case BaselineSpecialParameter::ENV: {
126                    StackSlotOperand slotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
127                        stackOffsetDescriptor.GetSpecialRegisterOffset(SpecialRegister::ENV));
128                    macroParameters.emplace_back(slotOpnd);
129                    break;
130                }
131                default:
132                    macroParameters.emplace_back(std::get<BaselineSpecialParameter>(param));
133            }
134        } else if (std::holds_alternative<int8_t>(param)) {
135            macroParameters.emplace_back(std::get<int8_t>(param));
136        } else if (std::holds_alternative<int16_t>(param)) {
137            macroParameters.emplace_back(std::get<int16_t>(param));
138        } else if (std::holds_alternative<int32_t>(param)) {
139            macroParameters.emplace_back(std::get<int32_t>(param));
140        } else if (std::holds_alternative<int64_t>(param)) {
141            macroParameters.emplace_back(std::get<int64_t>(param));
142        } else {
143            VirtualRegister vReg = std::get<VirtualRegister>(param);
144            StackSlotOperand slotOpnd(StackSlotOperand::BaseRegister::FRAME_REGISTER,
145                stackOffsetDescriptor.GetVregOffset(vReg));
146            macroParameters.emplace_back(slotOpnd);
147        }
148    }
149    macroAssembler->CallBuiltin(funcAddress, macroParameters);
150}
151
152}  // namespace panda::ecmascript::kungfu
153