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() const53 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 Movl(Register dst, const Operand& src); 147 void Movzbq(const Operand &src, Register dst); 148 void Movzbl(const Operand &src, Register dst); 149 void Movzbl(Register src, Register dst); 150 void Movabs(uint64_t src, Register dst); 151 void Shrq(Immediate src, Register dst); 152 void Shrl(Immediate src, Register dst); 153 void Shr(Immediate src, Register dst); 154 void Shll(Immediate src, Register dst); 155 void Shlq(Immediate src, Register dst); 156 void Btsl(Register src, Register dst); 157 void Testq(Immediate src, Register dst); 158 void Testb(Immediate src, Register dst); 159 void Int3(); 160 void Movzwq(const Operand &src, Register dst); 161 162 private: EmitRexPrefix(const Register &x)163 void EmitRexPrefix(const Register &x) 164 { 165 if (HighBit(x) != 0) { 166 EmitU8(REX_PREFIX_B); 167 } 168 } 169 EmitRexPrefixW(const Register &rm)170 void EmitRexPrefixW(const Register &rm) 171 { 172 EmitU8(REX_PREFIX_W | HighBit(rm)); 173 } 174 EmitRexPrefixL(const Register &rm)175 void EmitRexPrefixL(const Register &rm) 176 { 177 EmitU8(REX_PREFIX_FIXED_BITS | HighBit(rm)); 178 } 179 EmitRexPrefix(const Operand &rm)180 void EmitRexPrefix(const Operand &rm) 181 { 182 // 0: Extension to the MODRM.rm field B 183 EmitU8(REX_PREFIX_W | rm.rex_); 184 } 185 EmitRexPrefix(Register reg, Register rm)186 void EmitRexPrefix(Register reg, Register rm) 187 { 188 // 0: Extension to the MODRM.rm field B 189 // 2: Extension to the MODRM.reg field R 190 EmitU8(REX_PREFIX_W | (HighBit(reg) << 2) | HighBit(rm)); 191 } 192 EmitRexPrefixl(Register reg, Register rm)193 void EmitRexPrefixl(Register reg, Register rm) 194 { 195 // 0: Extension to the MODRM.rm field B 196 if (HighBit(reg) != 0 || HighBit(rm) != 0) { 197 // 2: Extension to the MODRM.reg field R 198 EmitU8(REX_PREFIX_FIXED_BITS | (HighBit(reg) << 2) | HighBit(rm)); 199 } 200 } 201 EmitRexPrefix(Register reg, Operand rm)202 void EmitRexPrefix(Register reg, Operand rm) 203 { 204 // 0: Extension to the MODRM.rm field B 205 // 2: Extension to the MODRM.reg field R 206 EmitU8(REX_PREFIX_W | (HighBit(reg) << 2) | rm.rex_); 207 } 208 EmitRexPrefixl(Register reg, Operand rm)209 void EmitRexPrefixl(Register reg, Operand rm) 210 { 211 // 0: Extension to the MODRM.rm field B 212 if (HighBit(reg) != 0 || rm.rex_ != 0) { 213 // 2: Extension to the MODRM.reg field R 214 EmitU8(REX_PREFIX_FIXED_BITS | (HighBit(reg) << 2) | rm.rex_); 215 } 216 } 217 218 // +---+---+---+---+---+---+---+---+ 219 // | mod | reg | rm | 220 // +---+---+---+---+---+---+---+---+ EmitModrm(int32_t reg, Register rm)221 void EmitModrm(int32_t reg, Register rm) 222 { 223 EmitU8(MODE_RM | (static_cast<uint32_t>(reg) << LOW_BITS_SIZE) | LowBits(rm)); 224 } 225 EmitModrm(Register reg, Register rm)226 void EmitModrm(Register reg, Register rm) 227 { 228 EmitModrm(LowBits(reg), rm); 229 } 230 EmitOperand(Register reg, Operand rm)231 void EmitOperand(Register reg, Operand rm) 232 { 233 EmitOperand(LowBits(reg), rm); 234 } 235 void EmitOperand(int32_t reg, Operand rm); 236 void EmitJmp(int32_t offset); 237 void EmitJa(int32_t offset); 238 void EmitJb(int32_t offset); 239 void EmitJz(int32_t offset); 240 void EmitJne(int32_t offset); 241 void EmitJbe(int32_t offset); 242 void EmitJnz(int32_t offset); 243 void EmitJle(int32_t offset); 244 void EmitJae(int32_t offset); 245 void EmitJg(int32_t offset); 246 void EmitJge(int32_t offset); 247 void EmitJe(int32_t offset); 248 void EmitCall(int32_t offset); 249 void EmitJnb(int32_t offset); 250 // +---+---+---+---+---+---+---+---+ 251 // | 0 1 0 0 | W | R | X | B | 252 // +---+---+---+---+---+---+---+---+ 253 static constexpr uint8_t REX_PREFIX_FIXED_BITS = 0x40; 254 static constexpr uint8_t REX_PREFIX_B = 0x41; 255 static constexpr uint8_t REX_PREFIX_W = 0x48; 256 // b11 257 static constexpr uint8_t MODE_RM = 0xC0; 258 // low bits: 3, high bit 1 259 static constexpr size_t LOW_BITS_SIZE = 3; 260 static constexpr size_t LOW_BITS_MASK = (1 << LOW_BITS_SIZE) - 1; 261 262 static constexpr int32_t SIZE_OF_INT8 = static_cast<int32_t>(sizeof(int8_t)); 263 static constexpr int32_t SIZE_OF_INT32 = static_cast<int32_t>(sizeof(int32_t)); 264 GetModrm(int32_t mode, Register rm)265 static uint8_t GetModrm(int32_t mode, Register rm) 266 { 267 // [r/m] 268 // [r/m + disp8] 269 // [r/m + disp32] 270 // 6: offset of mode 271 return (static_cast<uint32_t>(mode) << 6) | LowBits(rm); 272 } GetModrmRex(Register rm)273 static uint8_t GetModrmRex(Register rm) 274 { 275 return HighBit(rm); 276 } 277 // +---+---+---+---+---+---+---+---+ 278 // | scale | index | base | 279 // +---+---+---+---+---+---+---+---+ GetSIB(Scale scale, Register index, Register base)280 static uint8_t GetSIB(Scale scale, Register index, Register base) 281 { 282 // 6: offset of scale 283 return (static_cast<uint8_t>(scale) << 6) | (LowBits(index) << LOW_BITS_SIZE) | 284 LowBits(base); 285 } GetSIBRex(Register index, Register base)286 static uint8_t GetSIBRex(Register index, Register base) 287 { 288 return (HighBit(index) << 1) | HighBit(base); 289 } LowBits(Register x)290 static uint32_t LowBits(Register x) 291 { 292 return static_cast<uint8_t>(x) & LOW_BITS_MASK; 293 } HighBit(Register x)294 static uint32_t HighBit(Register x) 295 { 296 return static_cast<uint8_t>(x) >> LOW_BITS_SIZE; 297 } 298 friend class Operand; 299 }; 300 } // panda::ecmascript::x64 301 #endif // ECMASCRIPT_COMPILER_ASSEMBLER_X64_H 302