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