1/* 2 * Copyright (c) 2022 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#ifndef ECMASCRIPT_COMPILER_AARCH64_EXTEND_ASSEMBLER_H 17#define ECMASCRIPT_COMPILER_AARCH64_EXTEND_ASSEMBLER_H 18 19#include "ecmascript/compiler/assembler/aarch64/assembler_aarch64.h" 20#include "ecmascript/compiler/assembler_module.h" 21#include "ecmascript/compiler/bc_call_signature.h" 22 23namespace panda::ecmascript::aarch64 { 24using namespace panda::ecmascript::kungfu; 25// ExtendAssembler implements frequently-used assembler macros. 26class ExtendedAssembler : public AssemblerAarch64 { 27public: 28 static constexpr int FRAME_SLOT_SIZE = 8; 29 static constexpr int PAIR_SLOT_SIZE = 16; 30 ExtendedAssembler(Chunk *chunk, AssemblerModule *module) 31 : AssemblerAarch64(chunk), module_(module) 32 { 33 } 34 void BindAssemblerStub(int id); 35 void CalleeSave(); 36 void CalleeRestore(); 37 void CallAssemblerStub(int id, bool isTail = false); 38 void PushFpAndLr(); 39 void SaveFpAndLr(); 40 void RestoreFpAndLr(); 41 void PushLrAndFp(); 42 void SaveLrAndFp(); 43 void RestoreLrAndFp(); 44 void PushArgc(int32_t argc, Register op, Register fp); 45 void PushArgc(Register argc, Register op, Register fp); 46 void Align16(Register fp); 47 48 Register TempRegister1() 49 { 50 if (temp1InUse_) { 51 LOG_COMPILER(FATAL) << "temp register1 inuse."; 52 UNREACHABLE(); 53 } 54 temp1InUse_ = true; 55 return X9; 56 } 57 Register TempRegister2() 58 { 59 if (temp2InUse_) { 60 LOG_COMPILER(FATAL) << "temp register2 inuse."; 61 UNREACHABLE(); 62 } 63 temp2InUse_ = true; 64 return X10; 65 } 66 Register AvailableRegister1() const 67 { 68 // X11 is neither callee saved reegister nor argument register 69 return X11; 70 } 71 Register AvailableRegister2() const 72 { 73 // X12 is neither callee saved reegister nor argument register 74 return X12; 75 } 76 Register AvailableRegister3() const 77 { 78 // X13 is neither callee saved reegister nor argument register 79 return X13; 80 } 81 Register AvailableRegister4() const 82 { 83 // X14 is neither callee saved reegister nor argument register 84 return X14; 85 } 86 Register CallDispatcherArgument(kungfu::CallDispatchInputs index) 87 { 88 size_t i = static_cast<size_t>(index); 89 Register ret = isGhcCallingConv_ ? ghcJSCallDispacherArgs_[i] : cppJSCallDispacherArgs_[i]; 90 if (ret.GetId() == INVALID_REG) { 91 LOG_COMPILER(FATAL) << "arm64 invalid call argument:" << i; 92 } 93 return ret; 94 } 95 Register GlueRegister() 96 { 97 return isGhcCallingConv_ ? X19 : X0; 98 } 99 100 bool FromInterpreterHandler() const 101 { 102 return isGhcCallingConv_; 103 } 104private: 105 AssemblerModule *module_ {nullptr}; 106 bool isGhcCallingConv_ {false}; 107 bool temp1InUse_ {false}; 108 bool temp2InUse_ {false}; 109 friend class TempRegister1Scope; 110 friend class TempRegister2Scope; 111 112 static constexpr size_t JS_CALL_DISPATCHER_ARGS_COUNT = 113 static_cast<size_t>(kungfu::CallDispatchInputs::NUM_OF_INPUTS); 114 static Register ghcJSCallDispacherArgs_[JS_CALL_DISPATCHER_ARGS_COUNT]; 115 static Register cppJSCallDispacherArgs_[JS_CALL_DISPATCHER_ARGS_COUNT]; 116}; 117 118class TempRegister1Scope { 119public: 120 explicit TempRegister1Scope(ExtendedAssembler *assembler) : assembler_(assembler) {} 121 ~TempRegister1Scope() 122 { 123 assembler_->temp1InUse_ = false; 124 } 125 126 NO_COPY_SEMANTIC(TempRegister1Scope); 127 NO_MOVE_SEMANTIC(TempRegister1Scope); 128private: 129 ExtendedAssembler *assembler_; 130}; 131 132class TempRegister2Scope { 133public: 134 explicit TempRegister2Scope(ExtendedAssembler *assembler) : assembler_(assembler) {} 135 ~TempRegister2Scope() 136 { 137 assembler_->temp2InUse_ = false; 138 } 139 140 NO_COPY_SEMANTIC(TempRegister2Scope); 141 NO_MOVE_SEMANTIC(TempRegister2Scope); 142private: 143 ExtendedAssembler *assembler_; 144}; 145} // panda::ecmascript::aarch64 146#endif // ECMASCRIPT_COMPILER_AARCH64_EXTEND_ASSEMBLER_H