• 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 
16 #ifndef ECMASCRIPT_COMPILER_ASSEMBLER_AARCH64_H
17 #define ECMASCRIPT_COMPILER_ASSEMBLER_AARCH64_H
18 
19 #include <map>
20 
21 #include "ecmascript/compiler/assembler/assembler.h"
22 #include "ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h"
23 
24 namespace panda::ecmascript::aarch64 {
25 class Register {
26 public:
reg_(reg)27     Register(RegisterId reg, RegisterType type = RegisterType::X) : reg_(reg), type_(type) {};
28 
W()29     Register W() const
30     {
31         return Register(reg_, RegisterType::W);
32     }
33 
X()34     Register X() const
35     {
36         return Register(reg_, RegisterType::X);
37     }
38 
GetType()39     RegisterType GetType() const
40     {
41         return type_;
42     }
43 
IsSp()44     inline bool IsSp() const
45     {
46         return reg_ == RegisterId::SP;
47     }
48 
IsW()49     inline bool IsW() const
50     {
51         return type_ == RegisterType::W;
52     }
53 
GetId()54     inline RegisterId GetId() const
55     {
56         return reg_;
57     }
58 
IsValid()59     inline bool IsValid() const
60     {
61         return reg_ != RegisterId::INVALID_REG;
62     }
63 
64     inline bool operator !=(const Register &other)
65     {
66         return reg_ != other.GetId() || type_ != other.GetType();
67     }
68 
69     inline bool operator ==(const Register &other)
70     {
71         return reg_ == other.GetId() && type_ == other.GetType();
72     }
73 
74 private:
75     RegisterId reg_;
76     RegisterType type_;
77 };
78 
79 class VectorRegister {
80 public:
reg_(reg)81     explicit VectorRegister(VectorRegisterId reg, Scale scale = D) : reg_(reg), scale_(scale) {};
82 
GetId()83     inline VectorRegisterId GetId() const
84     {
85         return reg_;
86     }
87 
IsValid()88     inline bool IsValid() const
89     {
90         return reg_ != VectorRegisterId::INVALID_VREG;
91     }
92 
GetScale()93     inline Scale GetScale() const
94     {
95         return scale_;
96     }
97 
GetRegSize()98     inline int GetRegSize() const
99     {
100         if (scale_ == B) {
101             return 8; // 8:Register size
102         } else if (scale_ == H) {
103             return 16; // 16:Register size
104         } else if (scale_ == S) {
105             return 32; // 32:Register size
106         } else if (scale_ == D) {
107             return 64; // 64:Register size
108         } else if (scale_ == Q) {
109             return 128; // 128:Register size
110         }
111         LOG_ECMA(FATAL) << "this branch is unreachable";
112         UNREACHABLE();
113     }
114 private:
115     VectorRegisterId reg_;
116     Scale scale_;
117 };
118 
119 class Immediate {
120 public:
Immediate(int64_t value)121     Immediate(int64_t value) : value_(value) {}
122     ~Immediate() = default;
123 
Value()124     int64_t Value() const
125     {
126         return value_;
127     }
128 private:
129     int64_t value_;
130 };
131 
132 class LogicalImmediate {
133 public:
134     static LogicalImmediate Create(uint64_t imm, int width);
Value()135     int Value() const
136     {
137         ASSERT(IsValid());
138         return imm_;
139     }
140 
IsValid()141     bool IsValid() const
142     {
143         return imm_ != InvalidLogicalImmediate;
144     }
145 
Is64bit()146     bool Is64bit() const
147     {
148         return imm_ & BITWISE_OP_N_MASK;
149     }
150 private:
LogicalImmediate(int value)151     explicit LogicalImmediate(int value)
152         : imm_(value)
153     {
154     }
155     static const int InvalidLogicalImmediate = -1;
156     int imm_;
157 };
158 
159 class Operand {
160 public:
Operand(Immediate imm)161     Operand(Immediate imm)
162         : reg_(RegisterId::INVALID_REG), extend_(Extend::NO_EXTEND), shift_(Shift::NO_SHIFT),
163           shiftAmount_(0), immediate_(imm)
164     {
165     }
166     Operand(Register reg, Shift shift = Shift::LSL, uint8_t shift_amount = 0)
reg_(reg)167         : reg_(reg), extend_(Extend::NO_EXTEND), shift_(shift), shiftAmount_(shift_amount), immediate_(0)
168     {
169     }
170     Operand(Register reg, Extend extend, uint8_t shiftAmount = 0)
reg_(reg)171         : reg_(reg), extend_(extend), shift_(Shift::NO_SHIFT), shiftAmount_(shiftAmount), immediate_(0)
172     {
173     }
174     ~Operand() = default;
175 
IsImmediate()176     inline bool IsImmediate() const
177     {
178         return !reg_.IsValid();
179     }
180 
IsShifted()181     inline bool IsShifted() const
182     {
183         return reg_.IsValid() && shift_ != Shift::NO_SHIFT;
184     }
185 
IsExtended()186     inline bool IsExtended() const
187     {
188         return reg_.IsValid() && extend_ != Extend::NO_EXTEND;
189     }
190 
Reg()191     inline Register Reg() const
192     {
193         return reg_;
194     }
195 
GetShiftOption()196     inline Shift GetShiftOption() const
197     {
198         return shift_;
199     }
200 
GetExtendOption()201     inline Extend GetExtendOption() const
202     {
203         return extend_;
204     }
205 
GetShiftAmount()206     inline uint8_t GetShiftAmount() const
207     {
208         return shiftAmount_;
209     }
210 
ImmediateValue()211     inline int64_t ImmediateValue() const
212     {
213         return immediate_.Value();
214     }
215 
GetImmediate()216     inline Immediate GetImmediate() const
217     {
218         return immediate_;
219     }
220 private:
221     Register reg_;
222     Extend  extend_;
223     Shift  shift_;
224     uint8_t  shiftAmount_;
225     Immediate immediate_;
226 };
227 
228 class MemoryOperand {
229 public:
230     MemoryOperand(Register base, Register offset, Extend extend, uint8_t  shiftAmount = 0)
base_(base)231         : base_(base), offsetReg_(offset), offsetImm_(0), addrmod_(AddrMode::OFFSET),
232           extend_(extend), shift_(Shift::NO_SHIFT), shiftAmount_(shiftAmount)
233     {
234     }
235     MemoryOperand(Register base, Register offset, Shift shift = Shift::NO_SHIFT, uint8_t  shiftAmount = 0)
base_(base)236         : base_(base), offsetReg_(offset), offsetImm_(0), addrmod_(AddrMode::OFFSET),
237           extend_(Extend::NO_EXTEND), shift_(shift), shiftAmount_(shiftAmount)
238     {
239     }
240     MemoryOperand(Register base, int64_t offset, AddrMode addrmod = AddrMode::OFFSET)
base_(base)241         : base_(base), offsetReg_(RegisterId::INVALID_REG), offsetImm_(offset), addrmod_(addrmod),
242           extend_(Extend::NO_EXTEND), shift_(Shift::NO_SHIFT), shiftAmount_(0)
243     {
244     }
245     ~MemoryOperand() = default;
246 
GetRegBase()247     Register GetRegBase() const
248     {
249         return base_;
250     }
251 
IsImmediateOffset()252     bool IsImmediateOffset() const
253     {
254         return !offsetReg_.IsValid();
255     }
256 
GetImmediate()257     Immediate GetImmediate() const
258     {
259         return offsetImm_;
260     }
261 
GetAddrMode()262     AddrMode GetAddrMode() const
263     {
264         return addrmod_;
265     }
266 
GetExtendOption()267     Extend GetExtendOption() const
268     {
269         return extend_;
270     }
271 
GetShiftOption()272     Shift GetShiftOption() const
273     {
274         return shift_;
275     }
276 
GetShiftAmount()277     uint8_t GetShiftAmount() const
278     {
279         return shiftAmount_;
280     }
281 
GetRegisterOffset()282     Register GetRegisterOffset() const
283     {
284         return offsetReg_;
285     }
286 private:
287     Register base_;
288     Register offsetReg_;
289     Immediate offsetImm_;
290     AddrMode addrmod_;
291     Extend extend_;
292     Shift shift_;
293     uint8_t shiftAmount_;
294 };
295 
296 class AssemblerAarch64 : public Assembler {
297 public:
AssemblerAarch64(Chunk * chunk)298     explicit AssemblerAarch64(Chunk *chunk)
299         : Assembler(chunk)
300     {
301     }
302     void Ldp(const Register &rt, const Register &rt2, const MemoryOperand &operand);
303     void Stp(const Register &rt, const Register &rt2, const MemoryOperand &operand);
304     void Ldp(const VectorRegister &vt, const VectorRegister &vt2, const MemoryOperand &operand);
305     void Stp(const VectorRegister &vt, const VectorRegister &vt2, const MemoryOperand &operand);
306     void Ldr(const Register &rt, const MemoryOperand &operand);
307     void Ldrh(const Register &rt, const MemoryOperand &operand);
308     void Ldrb(const Register &rt, const MemoryOperand &operand);
309     void Str(const Register &rt, const MemoryOperand &operand);
310     void Ldur(const Register &rt, const MemoryOperand &operand);
311     void Stur(const Register &rt, const MemoryOperand &operand);
312     void Mov(const Register &rd, const Immediate &imm);
313     void Mov(const Register &rd, const Register &rm);
314     void Movz(const Register &rd, uint64_t imm, int shift);
315     void Movk(const Register &rd, uint64_t imm, int shift);
316     void Movn(const Register &rd, uint64_t imm, int shift);
317     void Orr(const Register &rd, const Register &rn, const LogicalImmediate &imm);
318     void Orr(const Register &rd, const Register &rn, const Operand &operand);
319     void And(const Register &rd, const Register &rn, const Operand &operand);
320     void Ands(const Register &rd, const Register &rn, const Operand &operand);
321     void And(const Register &rd, const Register &rn, const LogicalImmediate &imm);
322     void Ands(const Register &rd, const Register &rn, const LogicalImmediate &imm);
323     void Lsr(const Register &rd, const Register &rn, unsigned shift);
324     void Lsl(const Register &rd, const Register &rn, const Register &rm);
325     void Lsr(const Register &rd, const Register &rn, const Register &rm);
326     void Ubfm(const Register &rd, const Register &rn, unsigned immr, unsigned imms);
327     void Bfm(const Register &rd, const Register &rn, unsigned immr, unsigned imms);
328 
329     void Add(const Register &rd, const Register &rn, const Operand &operand);
330     void Adds(const Register &rd, const Register &rn, const Operand &operand);
331     void Sub(const Register &rd, const Register &rn, const Operand &operand);
332     void Subs(const Register &rd, const Register &rn, const Operand &operand);
333     void Cmp(const Register &rd, const Operand &operand);
334     void CMov(const Register &rd, const Register &rn, const Operand &operand, Condition cond);
335     void B(Label *label);
336     void B(int32_t imm);
337     void B(Condition cond, Label *label);
338     void B(Condition cond, int32_t imm);
339     void Br(const Register &rn);
340     void Blr(const Register &rn);
341     void Bl(Label *label);
342     void Bl(int32_t imm);
343     void Cbz(const Register &rt, int32_t imm);
344     void Cbz(const Register &rt, Label *label);
345     void Cbnz(const Register &rt, int32_t imm);
346     void Cbnz(const Register &rt, Label *label);
347     void Tbz(const Register &rt, int32_t bitPos, Label *label);
348     void Tbz(const Register &rt, int32_t bitPos, int32_t imm);
349     void Tbnz(const Register &rt, int32_t bitPos, Label *label);
350     void Tbnz(const Register &rt, int32_t bitPos, int32_t imm);
351     void Tst(const Register &rn, const Operand &operand);
352     void Tst(const Register &rn, const LogicalImmediate &imm);
353     void Ret();
354     void Ret(const Register &rn);
355     void Brk(const Immediate &imm);
356     void Bind(Label *target);
357 private:
358     // common reg field defines
Rd(uint32_t id)359     inline uint32_t Rd(uint32_t id)
360     {
361         return (id << COMMON_REG_Rd_LOWBITS) & COMMON_REG_Rd_MASK;
362     }
363 
Rn(uint32_t id)364     inline uint32_t Rn(uint32_t id)
365     {
366         return (id << COMMON_REG_Rn_LOWBITS) & COMMON_REG_Rn_MASK;
367     }
368 
Rm(uint32_t id)369     inline uint32_t Rm(uint32_t id)
370     {
371         return (id << COMMON_REG_Rm_LOWBITS) & COMMON_REG_Rm_MASK;
372     }
373 
Rt(uint32_t id)374     inline uint32_t Rt(uint32_t id)
375     {
376         return (id << COMMON_REG_Rt_LOWBITS) & COMMON_REG_Rt_MASK;
377     }
378 
Rt2(uint32_t id)379     inline uint32_t Rt2(uint32_t id)
380     {
381         return (id << COMMON_REG_Rt2_LOWBITS) & COMMON_REG_Rt2_MASK;
382     }
383 
Sf(uint32_t id)384     inline uint32_t Sf(uint32_t id)
385     {
386         return (id << COMMON_REG_Sf_LOWBITS) & COMMON_REG_Sf_MASK;
387     }
388 
LoadAndStorePairImm(uint32_t imm)389     inline uint32_t LoadAndStorePairImm(uint32_t imm)
390     {
391         return (((imm) << LDP_STP_Imm7_LOWBITS) & LDP_STP_Imm7_MASK);
392     }
393 
LoadAndStoreImm(uint32_t imm,bool isSigned)394     inline uint32_t LoadAndStoreImm(uint32_t imm, bool isSigned)
395     {
396         if (isSigned) {
397             return (imm << LDR_STR_Imm9_LOWBITS) & LDR_STR_Imm9_MASK;
398         } else {
399             return (imm << LDR_STR_Imm12_LOWBITS) & LDR_STR_Imm12_MASK;
400         }
401     }
402 
BranchImm19(uint32_t imm)403     inline uint32_t BranchImm19(uint32_t imm)
404     {
405         return (imm << BRANCH_Imm19_LOWBITS) & BRANCH_Imm19_MASK;
406     }
407 
408     uint32_t GetOpcFromScale(Scale scale, bool ispair);
409     bool IsAddSubImm(uint64_t imm);
410     void AddSubImm(AddSubOpCode op, const Register &rd, const Register &rn, bool setFlags, uint64_t imm);
411     void AddSubReg(AddSubOpCode op, const Register &rd, const Register &rn, bool setFlags, const Operand &operand);
412     void MovWide(uint32_t op, const Register &rd, uint64_t imm, int shift);
413     void BitWiseOpImm(BitwiseOpCode op, const Register &rd, const Register &rn, uint64_t imm);
414     void BitWiseOpShift(BitwiseOpCode op, const Register &rd, const Register &rn, const Operand &operand);
415     bool TrySequenceOfOnes(const Register &rd, uint64_t imm);
416     bool TryReplicateHWords(const Register &rd, uint64_t imm);
417     void EmitMovInstruct(const Register &rd, uint64_t imm,
418                          unsigned int allOneHWords, unsigned int allZeroHWords);
419     int32_t GetLinkOffsetFromBranchInst(int32_t pos);
420     int32_t LinkAndGetInstOffsetToLabel(Label *label);
421     int32_t ImmBranch(uint32_t branchCode);
422     void SetRealOffsetToBranchInst(uint32_t linkPos, int32_t disp);
423     void Ldr(const Register &rt, const MemoryOperand &operand, Scale scale);
424     uint64_t GetImmOfLdr(const MemoryOperand &operand, Scale scale, bool isRegX);
425     uint64_t GetOpcodeOfLdr(const MemoryOperand &operand, Scale scale);
426     uint32_t GetShiftOfLdr(const MemoryOperand &operand, Scale scale, bool isRegX);
427 };
428 }  // namespace panda::ecmascript::aarch64
429 #endif
430