14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2022 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#ifndef ECMASCRIPT_COMPILER_AARCH64_EXTEND_ASSEMBLER_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_COMPILER_AARCH64_EXTEND_ASSEMBLER_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/compiler/assembler/aarch64/assembler_aarch64.h"
204514f5e3Sopenharmony_ci#include "ecmascript/compiler/assembler_module.h"
214514f5e3Sopenharmony_ci#include "ecmascript/compiler/bc_call_signature.h"
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_cinamespace panda::ecmascript::aarch64 {
244514f5e3Sopenharmony_ciusing namespace panda::ecmascript::kungfu;
254514f5e3Sopenharmony_ci// ExtendAssembler implements frequently-used assembler macros.
264514f5e3Sopenharmony_ciclass ExtendedAssembler : public AssemblerAarch64 {
274514f5e3Sopenharmony_cipublic:
284514f5e3Sopenharmony_ci    static constexpr int FRAME_SLOT_SIZE = 8;
294514f5e3Sopenharmony_ci    static constexpr int PAIR_SLOT_SIZE = 16;
304514f5e3Sopenharmony_ci    ExtendedAssembler(Chunk *chunk, AssemblerModule *module)
314514f5e3Sopenharmony_ci        : AssemblerAarch64(chunk), module_(module)
324514f5e3Sopenharmony_ci    {
334514f5e3Sopenharmony_ci    }
344514f5e3Sopenharmony_ci    void BindAssemblerStub(int id);
354514f5e3Sopenharmony_ci    void CalleeSave();
364514f5e3Sopenharmony_ci    void CalleeRestore();
374514f5e3Sopenharmony_ci    void CallAssemblerStub(int id, bool isTail = false);
384514f5e3Sopenharmony_ci    void PushFpAndLr();
394514f5e3Sopenharmony_ci    void SaveFpAndLr();
404514f5e3Sopenharmony_ci    void RestoreFpAndLr();
414514f5e3Sopenharmony_ci    void PushLrAndFp();
424514f5e3Sopenharmony_ci    void SaveLrAndFp();
434514f5e3Sopenharmony_ci    void RestoreLrAndFp();
444514f5e3Sopenharmony_ci    void PushArgc(int32_t argc, Register op, Register fp);
454514f5e3Sopenharmony_ci    void PushArgc(Register argc, Register op, Register fp);
464514f5e3Sopenharmony_ci    void Align16(Register fp);
474514f5e3Sopenharmony_ci
484514f5e3Sopenharmony_ci    Register TempRegister1()
494514f5e3Sopenharmony_ci    {
504514f5e3Sopenharmony_ci        if (temp1InUse_) {
514514f5e3Sopenharmony_ci            LOG_COMPILER(FATAL) << "temp register1 inuse.";
524514f5e3Sopenharmony_ci            UNREACHABLE();
534514f5e3Sopenharmony_ci        }
544514f5e3Sopenharmony_ci        temp1InUse_ = true;
554514f5e3Sopenharmony_ci        return X9;
564514f5e3Sopenharmony_ci    }
574514f5e3Sopenharmony_ci    Register TempRegister2()
584514f5e3Sopenharmony_ci    {
594514f5e3Sopenharmony_ci        if (temp2InUse_) {
604514f5e3Sopenharmony_ci            LOG_COMPILER(FATAL) << "temp register2 inuse.";
614514f5e3Sopenharmony_ci            UNREACHABLE();
624514f5e3Sopenharmony_ci        }
634514f5e3Sopenharmony_ci        temp2InUse_ = true;
644514f5e3Sopenharmony_ci        return X10;
654514f5e3Sopenharmony_ci    }
664514f5e3Sopenharmony_ci    Register AvailableRegister1() const
674514f5e3Sopenharmony_ci    {
684514f5e3Sopenharmony_ci        // X11 is neither callee saved reegister nor argument register
694514f5e3Sopenharmony_ci        return X11;
704514f5e3Sopenharmony_ci    }
714514f5e3Sopenharmony_ci    Register AvailableRegister2() const
724514f5e3Sopenharmony_ci    {
734514f5e3Sopenharmony_ci        // X12 is neither callee saved reegister nor argument register
744514f5e3Sopenharmony_ci        return X12;
754514f5e3Sopenharmony_ci    }
764514f5e3Sopenharmony_ci    Register AvailableRegister3() const
774514f5e3Sopenharmony_ci    {
784514f5e3Sopenharmony_ci        // X13 is neither callee saved reegister nor argument register
794514f5e3Sopenharmony_ci        return X13;
804514f5e3Sopenharmony_ci    }
814514f5e3Sopenharmony_ci    Register AvailableRegister4() const
824514f5e3Sopenharmony_ci    {
834514f5e3Sopenharmony_ci        // X14 is neither callee saved reegister nor argument register
844514f5e3Sopenharmony_ci        return X14;
854514f5e3Sopenharmony_ci    }
864514f5e3Sopenharmony_ci    Register CallDispatcherArgument(kungfu::CallDispatchInputs index)
874514f5e3Sopenharmony_ci    {
884514f5e3Sopenharmony_ci        size_t i = static_cast<size_t>(index);
894514f5e3Sopenharmony_ci        Register ret = isGhcCallingConv_ ? ghcJSCallDispacherArgs_[i] : cppJSCallDispacherArgs_[i];
904514f5e3Sopenharmony_ci        if (ret.GetId() == INVALID_REG) {
914514f5e3Sopenharmony_ci            LOG_COMPILER(FATAL) << "arm64 invalid call argument:" << i;
924514f5e3Sopenharmony_ci        }
934514f5e3Sopenharmony_ci        return ret;
944514f5e3Sopenharmony_ci    }
954514f5e3Sopenharmony_ci    Register GlueRegister()
964514f5e3Sopenharmony_ci    {
974514f5e3Sopenharmony_ci        return isGhcCallingConv_ ? X19 : X0;
984514f5e3Sopenharmony_ci    }
994514f5e3Sopenharmony_ci
1004514f5e3Sopenharmony_ci    bool FromInterpreterHandler() const
1014514f5e3Sopenharmony_ci    {
1024514f5e3Sopenharmony_ci        return isGhcCallingConv_;
1034514f5e3Sopenharmony_ci    }
1044514f5e3Sopenharmony_ciprivate:
1054514f5e3Sopenharmony_ci    AssemblerModule *module_ {nullptr};
1064514f5e3Sopenharmony_ci    bool isGhcCallingConv_ {false};
1074514f5e3Sopenharmony_ci    bool temp1InUse_ {false};
1084514f5e3Sopenharmony_ci    bool temp2InUse_ {false};
1094514f5e3Sopenharmony_ci    friend class TempRegister1Scope;
1104514f5e3Sopenharmony_ci    friend class TempRegister2Scope;
1114514f5e3Sopenharmony_ci
1124514f5e3Sopenharmony_ci    static constexpr size_t JS_CALL_DISPATCHER_ARGS_COUNT =
1134514f5e3Sopenharmony_ci        static_cast<size_t>(kungfu::CallDispatchInputs::NUM_OF_INPUTS);
1144514f5e3Sopenharmony_ci    static Register ghcJSCallDispacherArgs_[JS_CALL_DISPATCHER_ARGS_COUNT];
1154514f5e3Sopenharmony_ci    static Register cppJSCallDispacherArgs_[JS_CALL_DISPATCHER_ARGS_COUNT];
1164514f5e3Sopenharmony_ci};
1174514f5e3Sopenharmony_ci
1184514f5e3Sopenharmony_ciclass TempRegister1Scope {
1194514f5e3Sopenharmony_cipublic:
1204514f5e3Sopenharmony_ci    explicit TempRegister1Scope(ExtendedAssembler *assembler) : assembler_(assembler) {}
1214514f5e3Sopenharmony_ci    ~TempRegister1Scope()
1224514f5e3Sopenharmony_ci    {
1234514f5e3Sopenharmony_ci        assembler_->temp1InUse_ = false;
1244514f5e3Sopenharmony_ci    }
1254514f5e3Sopenharmony_ci
1264514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(TempRegister1Scope);
1274514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(TempRegister1Scope);
1284514f5e3Sopenharmony_ciprivate:
1294514f5e3Sopenharmony_ci    ExtendedAssembler *assembler_;
1304514f5e3Sopenharmony_ci};
1314514f5e3Sopenharmony_ci
1324514f5e3Sopenharmony_ciclass TempRegister2Scope {
1334514f5e3Sopenharmony_cipublic:
1344514f5e3Sopenharmony_ci    explicit TempRegister2Scope(ExtendedAssembler *assembler) : assembler_(assembler) {}
1354514f5e3Sopenharmony_ci    ~TempRegister2Scope()
1364514f5e3Sopenharmony_ci    {
1374514f5e3Sopenharmony_ci        assembler_->temp2InUse_ = false;
1384514f5e3Sopenharmony_ci    }
1394514f5e3Sopenharmony_ci
1404514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(TempRegister2Scope);
1414514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(TempRegister2Scope);
1424514f5e3Sopenharmony_ciprivate:
1434514f5e3Sopenharmony_ci    ExtendedAssembler *assembler_;
1444514f5e3Sopenharmony_ci};
1454514f5e3Sopenharmony_ci}  // panda::ecmascript::aarch64
1464514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_COMPILER_AARCH64_EXTEND_ASSEMBLER_H