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 #ifndef ECMASCRIPT_COMPILER_ASSEMBLER_X64_H 16 #define ECMASCRIPT_COMPILER_ASSEMBLER_X64_H 17 18 #include "ecmascript/compiler/assembler/assembler.h" 19 20 namespace panda::ecmascript::x64 { 21 enum Register : uint8_t { 22 rax = 0, 23 rcx, 24 rdx, 25 rbx, 26 rsp, 27 rbp, 28 rsi, 29 rdi, 30 r8, 31 r9, 32 r10, 33 r11, 34 r12, 35 r13, 36 r14, 37 r15, 38 rInvalid, 39 }; 40 41 enum Scale : uint8_t { 42 Times1 = 0, 43 Times2, 44 Times4, 45 Times8 46 }; 47 48 class Immediate { 49 public: Immediate(int32_t value)50 Immediate(int32_t value) : value_(value) {} 51 ~Immediate() = default; 52 Value()53 int32_t Value() const 54 { 55 return value_; 56 } 57 private: 58 int32_t value_; 59 }; 60 61 class Operand { 62 public: 63 Operand(Register base, int32_t disp); 64 Operand(Register base, Register index, Scale scale, int32_t disp); 65 Operand(Register index, Scale scale, int32_t disp); 66 ~Operand() = default; 67 68 void BuildSIB(Scale scale, Register index, Register base); 69 void BuildModerm(int32_t mode, Register rm); 70 void BuildDisp8(int32_t disp); 71 void BuildDisp32(int32_t disp); 72 int32_t disp_ = 0; 73 uint8_t rex_ = 0; 74 uint8_t sib_ = 0; 75 uint8_t moderm_ = 0; 76 bool hasSIB_ = false; 77 bool hasDisp8_ = false; 78 bool hasDisp32_ = false; 79 }; 80 81 // The Intel 64 instruction format is: 82 // | prefixs| opcode| modR/M| SIB| Displacement| Immediate| 83 class AssemblerX64 : public Assembler { 84 public: AssemblerX64(Chunk * chunk)85 explicit AssemblerX64(Chunk *chunk) 86 : Assembler(chunk) {} 87 ~AssemblerX64() = default; 88 89 void Pushq(Register x); 90 void Pushq(Immediate x); 91 void Push(Register x); 92 void Popq(Register x); 93 void Pop(Register x); 94 void Movq(Register src, Register dst); 95 void Movq(const Operand &src, Register dst); 96 void Movq(Register src, const Operand &dst); 97 void Movq(Immediate src, Operand dst); 98 void Movq(Immediate src, Register dst); 99 void Mov(const Operand &src, Register dst); 100 void Mov(Register src, Register dst); 101 void Addq(Immediate src, Register dst); 102 void Addq(Register src, Register dst); 103 void Addl(Immediate src, Register dst); 104 void Subq(Immediate src, Register dst); 105 void Subq(Register src, Register dst); 106 void Subl(Immediate src, Register dst); 107 void Cmpq(Immediate src, Register dst); 108 void Cmpq(Register src, Register dst); 109 void Cmpl(Immediate src, Register dst); 110 void Cmpb(Immediate src, Register dst); 111 void Cmp(Immediate src, Register dst); 112 void Callq(Register addr); 113 void Callq(Label *target); 114 void Ret(); 115 void Jmp(Label *target, Distance distance = Distance::Far); 116 void Jmp(Register dst); 117 void Jmp(Immediate offset); 118 void Bind(Label* target); 119 void Align16(); 120 121 void Andq(Immediate src, Register dst); 122 void Andl(Immediate src, Register dst); 123 void And(Register src, Register dst); 124 void Or(Immediate src, Register dst); 125 void Orq(Register src, Register dst); 126 void Btq(Immediate src, Register dst); 127 void Btl(Immediate src, Register dst); 128 void Cmpl(Register src, Register dst); 129 void CMovbe(Register src, Register dst); 130 void Ja(Label *target, Distance distance = Distance::Far); 131 void Jb(Label *target, Distance distance = Distance::Far); 132 void Jz(Label *target, Distance distance = Distance::Far); 133 void Je(Label *target, Distance distance = Distance::Far); 134 void Jg(Label *target, Distance distance = Distance::Far); 135 void Jge(Label *target, Distance distance = Distance::Far); 136 void Jne(Label *target, Distance distance = Distance::Far); 137 void Jbe(Label *target, Distance distance = Distance::Far); 138 void Jnz(Label *target, Distance distance = Distance::Far); 139 void Jle(Label *target, Distance distance = Distance::Far); 140 void Jae(Label *target, Distance distance = Distance::Far); 141 void Jnb(Label *target, Distance distance = Distance::Far); 142 void Leaq(const Operand &src, Register dst); 143 void Leal(const Operand &src, Register dst); 144 void Movl(Register src, Register dst); 145 void Movl(const Operand &src, Register dst); 146 void Movzbq(const Operand &src, Register dst); 147 void Movabs(uint64_t src, Register dst); 148 void Shrq(Immediate src, Register dst); 149 void Shr(Immediate src, Register dst); 150 void Shll(Immediate src, Register dst); 151 void Shlq(Immediate src, Register dst); 152 void Testq(Immediate src, Register dst); 153 void Testb(Immediate src, Register dst); 154 void Int3(); 155 void Movzwq(const Operand &src, Register dst); 156 157 private: EmitRexPrefix(const Register & x)158 void EmitRexPrefix(const Register &x) 159 { 160 if (HighBit(x) != 0) { 161 EmitU8(REX_PREFIX_B); 162 } 163 } 164 EmitRexPrefixW(const Register & rm)165 void EmitRexPrefixW(const Register &rm) 166 { 167 EmitU8(REX_PREFIX_W | HighBit(rm)); 168 } 169 EmitRexPrefixL(const Register & rm)170 void EmitRexPrefixL(const Register &rm) 171 { 172 EmitU8(REX_PREFIX_FIXED_BITS | HighBit(rm)); 173 } 174 EmitRexPrefix(const Operand & rm)175 void EmitRexPrefix(const Operand &rm) 176 { 177 // 0: Extension to the MODRM.rm field B 178 EmitU8(REX_PREFIX_W | rm.rex_); 179 } 180 EmitRexPrefix(Register reg,Register rm)181 void EmitRexPrefix(Register reg, Register rm) 182 { 183 // 0: Extension to the MODRM.rm field B 184 // 2: Extension to the MODRM.reg field R 185 EmitU8(REX_PREFIX_W | (HighBit(reg) << 2) | HighBit(rm)); 186 } 187 EmitRexPrefixl(Register reg,Register rm)188 void EmitRexPrefixl(Register reg, Register rm) 189 { 190 // 0: Extension to the MODRM.rm field B 191 if (HighBit(reg) != 0 || HighBit(rm) != 0) { 192 // 2: Extension to the MODRM.reg field R 193 EmitU8(REX_PREFIX_FIXED_BITS | (HighBit(reg) << 2) | HighBit(rm)); 194 } 195 } 196 EmitRexPrefix(Register reg,Operand rm)197 void EmitRexPrefix(Register reg, Operand rm) 198 { 199 // 0: Extension to the MODRM.rm field B 200 // 2: Extension to the MODRM.reg field R 201 EmitU8(REX_PREFIX_W | (HighBit(reg) << 2) | rm.rex_); 202 } 203 EmitRexPrefixl(Register reg,Operand rm)204 void EmitRexPrefixl(Register reg, Operand rm) 205 { 206 // 0: Extension to the MODRM.rm field B 207 if (HighBit(reg) != 0 || rm.rex_ != 0) { 208 // 2: Extension to the MODRM.reg field R 209 EmitU8(REX_PREFIX_FIXED_BITS | (HighBit(reg) << 2) | rm.rex_); 210 } 211 } 212 213 // +---+---+---+---+---+---+---+---+ 214 // | mod | reg | rm | 215 // +---+---+---+---+---+---+---+---+ EmitModrm(int32_t reg,Register rm)216 void EmitModrm(int32_t reg, Register rm) 217 { 218 EmitU8(MODE_RM | (static_cast<uint32_t>(reg) << LOW_BITS_SIZE) | LowBits(rm)); 219 } 220 EmitModrm(Register reg,Register rm)221 void EmitModrm(Register reg, Register rm) 222 { 223 EmitModrm(LowBits(reg), rm); 224 } 225 EmitOperand(Register reg,Operand rm)226 void EmitOperand(Register reg, Operand rm) 227 { 228 EmitOperand(LowBits(reg), rm); 229 } 230 void EmitOperand(int32_t reg, Operand rm); 231 void EmitJmp(int32_t offset); 232 void EmitJa(int32_t offset); 233 void EmitJb(int32_t offset); 234 void EmitJz(int32_t offset); 235 void EmitJne(int32_t offset); 236 void EmitJbe(int32_t offset); 237 void EmitJnz(int32_t offset); 238 void EmitJle(int32_t offset); 239 void EmitJae(int32_t offset); 240 void EmitJg(int32_t offset); 241 void EmitJge(int32_t offset); 242 void EmitJe(int32_t offset); 243 void EmitCall(int32_t offset); 244 void EmitJnb(int32_t offset); 245 // +---+---+---+---+---+---+---+---+ 246 // | 0 1 0 0 | W | R | X | B | 247 // +---+---+---+---+---+---+---+---+ 248 static constexpr uint8_t REX_PREFIX_FIXED_BITS = 0x40; 249 static constexpr uint8_t REX_PREFIX_B = 0x41; 250 static constexpr uint8_t REX_PREFIX_W = 0x48; 251 // b11 252 static constexpr uint8_t MODE_RM = 0xC0; 253 // low bits: 3, high bit 1 254 static constexpr size_t LOW_BITS_SIZE = 3; 255 static constexpr size_t LOW_BITS_MASK = (1 << LOW_BITS_SIZE) - 1; 256 GetModrm(int32_t mode,Register rm)257 static uint8_t GetModrm(int32_t mode, Register rm) 258 { 259 // [r/m] 260 // [r/m + disp8] 261 // [r/m + disp32] 262 // 6: offset of mode 263 return (static_cast<uint32_t>(mode) << 6) | LowBits(rm); 264 } GetModrmRex(Register rm)265 static uint8_t GetModrmRex(Register rm) 266 { 267 return HighBit(rm); 268 } 269 // +---+---+---+---+---+---+---+---+ 270 // | scale | index | base | 271 // +---+---+---+---+---+---+---+---+ GetSIB(Scale scale,Register index,Register base)272 static uint8_t GetSIB(Scale scale, Register index, Register base) 273 { 274 // 6: offset of scale 275 return (static_cast<uint8_t>(scale) << 6) | (LowBits(index) << LOW_BITS_SIZE) | 276 LowBits(base); 277 } GetSIBRex(Register index,Register base)278 static uint8_t GetSIBRex(Register index, Register base) 279 { 280 return (HighBit(index) << 1) | HighBit(base); 281 } LowBits(Register x)282 static uint32_t LowBits(Register x) 283 { 284 return static_cast<uint8_t>(x) & LOW_BITS_MASK; 285 } HighBit(Register x)286 static uint32_t HighBit(Register x) 287 { 288 return static_cast<uint8_t>(x) >> LOW_BITS_SIZE; 289 } 290 friend class Operand; 291 }; 292 } // panda::ecmascript::x64 293 #endif // ECMASCRIPT_COMPILER_ASSEMBLER_X64_H 294