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/assembler/x64/macro_assembler_x64.h" 17#include "ecmascript/js_function.h" 18 19namespace panda::ecmascript::kungfu { 20using namespace panda::ecmascript; 21 22void MacroAssemblerX64::Move(const StackSlotOperand &dstStackSlot, Immediate value) 23{ 24 x64::Register baseReg = (dstStackSlot.IsFrameBase()) ? x64::rbp : x64::rsp; 25 x64::Operand dstOpnd(baseReg, dstStackSlot.GetOffset()); 26 assembler.Movabs(value.GetValue(), LOCAL_SCOPE_REGISTER); 27 assembler.Movq(LOCAL_SCOPE_REGISTER, dstOpnd); 28} 29 30void MacroAssemblerX64::Move(const StackSlotOperand &dstStackSlot, 31 const StackSlotOperand &srcStackSlot) 32{ 33 x64::Register dstBaseReg = (dstStackSlot.IsFrameBase()) ? x64::rbp : x64::rsp; 34 x64::Register srcBaseReg = (srcStackSlot.IsFrameBase()) ? x64::rbp : x64::rsp; 35 x64::Operand srcOpnd(srcBaseReg, srcStackSlot.GetOffset()); 36 x64::Operand dstOpnd(dstBaseReg, dstStackSlot.GetOffset()); 37 assembler.Movq(srcOpnd, LOCAL_SCOPE_REGISTER); 38 assembler.Movq(LOCAL_SCOPE_REGISTER, dstOpnd); 39} 40 41void MacroAssemblerX64::Cmp(const StackSlotOperand &stackSlot, Immediate value) 42{ 43 x64::Register baseReg = (stackSlot.IsFrameBase()) ? x64::rbp : x64::rsp; 44 x64::Operand opnd(baseReg, stackSlot.GetOffset()); 45 assembler.Movq(opnd, LOCAL_SCOPE_REGISTER); 46 assembler.Cmp(x64::Immediate(value.GetValue()), LOCAL_SCOPE_REGISTER); 47} 48 49void MacroAssemblerX64::Bind(JumpLabel &label) 50{ 51 assembler.Bind(&label); 52} 53 54void MacroAssemblerX64::Jz(JumpLabel &label) 55{ 56 assembler.Jz(&label); 57} 58 59void MacroAssemblerX64::Jnz(JumpLabel &label) 60{ 61 assembler.Jnz(&label); 62} 63 64void MacroAssemblerX64::Jump(JumpLabel &label) 65{ 66 assembler.Jmp(&label); 67} 68 69void MacroAssemblerX64::SaveReturnRegister(const StackSlotOperand &dstStackSlot) 70{ 71 x64::Register dstBaseReg = (dstStackSlot.IsFrameBase()) ? x64::rbp : x64::rsp; 72 x64::Operand dstOpnd(dstBaseReg, dstStackSlot.GetOffset()); 73 assembler.Movq(RETURN_REGISTER, dstOpnd); 74} 75 76void MacroAssemblerX64::MovParameterIntoParamReg(MacroParameter param, x64::Register paramReg) 77{ 78 if (std::holds_alternative<BaselineSpecialParameter>(param)) { 79 auto specialParam = std::get<BaselineSpecialParameter>(param); 80 switch (specialParam) { 81 case BaselineSpecialParameter::GLUE: { 82 assembler.Movq(GLUE_REGISTER, paramReg); 83 break; 84 } 85 case BaselineSpecialParameter::PROFILE_TYPE_INFO: { 86 assembler.Movq(x64::Operand(x64::rbp, FUNCTION_OFFSET_FROM_SP), LOCAL_SCOPE_REGISTER); 87 assembler.Movq( 88 x64::Operand(LOCAL_SCOPE_REGISTER, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET), 89 LOCAL_SCOPE_REGISTER); 90 assembler.Movq(x64::Operand(LOCAL_SCOPE_REGISTER, ProfileTypeInfoCell::VALUE_OFFSET), paramReg); 91 break; 92 } 93 case BaselineSpecialParameter::SP: { 94 assembler.Movq(x64::rbp, paramReg); 95 break; 96 } 97 case BaselineSpecialParameter::HOTNESS_COUNTER: { 98 assembler.Movq(x64::Operand(x64::rbp, FUNCTION_OFFSET_FROM_SP), LOCAL_SCOPE_REGISTER); 99 assembler.Movq( 100 x64::Operand(LOCAL_SCOPE_REGISTER, JSFunctionBase::METHOD_OFFSET), LOCAL_SCOPE_REGISTER); 101 assembler.Movzwq(x64::Operand(LOCAL_SCOPE_REGISTER, Method::LITERAL_INFO_OFFSET), paramReg); 102 break; 103 } 104 default: { 105 std::cout << "not supported BaselineSpecialParameter currently" << std::endl; 106 std::abort(); 107 } 108 } 109 return; 110 } 111 if (std::holds_alternative<int8_t>(param)) { 112 int16_t num = std::get<int8_t>(param); 113 assembler.Movq(panda::ecmascript::x64::Immediate(static_cast<int32_t>(num)), paramReg); 114 return; 115 } 116 if (std::holds_alternative<int16_t>(param)) { 117 int16_t num = std::get<int16_t>(param); 118 assembler.Movq(panda::ecmascript::x64::Immediate(static_cast<int32_t>(num)), paramReg); 119 return; 120 } 121 if (std::holds_alternative<int32_t>(param)) { 122 int32_t num = std::get<int32_t>(param); 123 assembler.Movq(panda::ecmascript::x64::Immediate(num), paramReg); 124 return; 125 } 126 if (std::holds_alternative<int64_t>(param)) { 127 int64_t num = std::get<int64_t>(param); 128 assembler.Movabs(num, paramReg); 129 return; 130 } 131 if (std::holds_alternative<StackSlotOperand>(param)) { 132 StackSlotOperand stackSlotOpnd = std::get<StackSlotOperand>(param); 133 x64::Register dstBaseReg = (stackSlotOpnd.IsFrameBase()) ? x64::rbp : x64::rsp; 134 x64::Operand paramOpnd(dstBaseReg, stackSlotOpnd.GetOffset()); 135 assembler.Movq(paramOpnd, paramReg); 136 return; 137 } 138 std::cout << "not supported other type of baseline parameters currently" << std::endl; 139 std::abort(); 140} 141 142void MacroAssemblerX64::CallBuiltin(Address funcAddress, 143 const std::vector<MacroParameter> ¶meters) 144{ 145 for (size_t i = 0; i < parameters.size(); ++i) { 146 auto param = parameters[i]; 147 if (i == PARAM_REGISTER_COUNT) { 148 std::cout << "should not pass parameters on the stack" << std::endl; 149 std::abort(); 150 } 151 MovParameterIntoParamReg(param, registerParamVec[i]); 152 } 153 assembler.Movabs(static_cast<uint64_t>(funcAddress), LOCAL_SCOPE_REGISTER); 154 assembler.Callq(LOCAL_SCOPE_REGISTER); 155} 156 157} // namespace panda::ecmascript::kungfu 158