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 23 namespace panda::ecmascript::aarch64 { 24 using namespace panda::ecmascript::kungfu; 25 // ExtendAssembler implements frequently-used assembler macros. 26 class ExtendedAssembler : public AssemblerAarch64 { 27 public: 28 static constexpr int FRAME_SLOT_SIZE = 8; 29 static constexpr int PAIR_SLOT_SIZE = 16; ExtendedAssembler(Chunk *chunk, AssemblerModule *module)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 TempRegister1()48 Register TempRegister1() 49 { 50 if (temp1InUse_) { 51 LOG_COMPILER(FATAL) << "temp register1 inuse."; 52 UNREACHABLE(); 53 } 54 temp1InUse_ = true; 55 return X9; 56 } TempRegister2()57 Register TempRegister2() 58 { 59 if (temp2InUse_) { 60 LOG_COMPILER(FATAL) << "temp register2 inuse."; 61 UNREACHABLE(); 62 } 63 temp2InUse_ = true; 64 return X10; 65 } AvailableRegister1() const66 Register AvailableRegister1() const 67 { 68 // X11 is neither callee saved reegister nor argument register 69 return X11; 70 } AvailableRegister2() const71 Register AvailableRegister2() const 72 { 73 // X12 is neither callee saved reegister nor argument register 74 return X12; 75 } AvailableRegister3() const76 Register AvailableRegister3() const 77 { 78 // X13 is neither callee saved reegister nor argument register 79 return X13; 80 } AvailableRegister4() const81 Register AvailableRegister4() const 82 { 83 // X14 is neither callee saved reegister nor argument register 84 return X14; 85 } CallDispatcherArgument(kungfu::CallDispatchInputs index)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 } GlueRegister()95 Register GlueRegister() 96 { 97 return isGhcCallingConv_ ? X19 : X0; 98 } 99 FromInterpreterHandler() const100 bool FromInterpreterHandler() const 101 { 102 return isGhcCallingConv_; 103 } 104 private: 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 118 class TempRegister1Scope { 119 public: TempRegister1Scope(ExtendedAssembler *assembler)120 explicit TempRegister1Scope(ExtendedAssembler *assembler) : assembler_(assembler) {} ~TempRegister1Scope()121 ~TempRegister1Scope() 122 { 123 assembler_->temp1InUse_ = false; 124 } 125 126 NO_COPY_SEMANTIC(TempRegister1Scope); 127 NO_MOVE_SEMANTIC(TempRegister1Scope); 128 private: 129 ExtendedAssembler *assembler_; 130 }; 131 132 class TempRegister2Scope { 133 public: TempRegister2Scope(ExtendedAssembler *assembler)134 explicit TempRegister2Scope(ExtendedAssembler *assembler) : assembler_(assembler) {} ~TempRegister2Scope()135 ~TempRegister2Scope() 136 { 137 assembler_->temp2InUse_ = false; 138 } 139 140 NO_COPY_SEMANTIC(TempRegister2Scope); 141 NO_MOVE_SEMANTIC(TempRegister2Scope); 142 private: 143 ExtendedAssembler *assembler_; 144 }; 145 } // panda::ecmascript::aarch64 146 #endif // ECMASCRIPT_COMPILER_AARCH64_EXTEND_ASSEMBLER_H