• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 MAPLEBE_INCLUDE_CG_ISA_H
17 #define MAPLEBE_INCLUDE_CG_ISA_H
18 
19 #include <cstdint>
20 #include "types_def.h"
21 #include "operand.h"
22 
23 namespace maplebe {
24 enum MopProperty : maple::uint8 {
25     kInsnIsAbstract,
26     kInsnIsMove,
27     kInsnIsLoad,
28     kInsnIsLoadPair,
29     kInsnIsStore,
30     kInsnIsStorePair,
31     kInsnIsAtomic,
32     kInsnIsCall,
33     kInsnIsTailCall,
34     kInsnIsConversion,
35     kInsnIsCondDef,
36     kInsnHasAcqure,
37     kInsnHasAcqureRCpc,
38     kInsnHasLOAcqure,
39     kInsnHasRelease,
40     kInsnHasLORelease,
41     kInsnCanThrow,
42     kInsnIsDMB,
43     kInsnIsUnCondBr,
44     kInsnIsCondBr,
45     kInsnHasLoop,
46     kInsnIsVectorOp,
47     kInsnIsBinaryOp,
48     kInsnIsPhi,
49     kInsnIsUnaryOp,
50     kInsnIsShift,
51     kInsnInlineAsm,
52     kInsnSpecialIntrisic,
53     kInsnIsNop,
54     kInsnIntrinsic,
55 };
56 using regno_t = uint32_t;
57 #define ISABSTRACT 1ULL
58 #define ISMOVE (1ULL << kInsnIsMove)
59 #define ISLOAD (1ULL << kInsnIsLoad)
60 #define ISLOADPAIR (1ULL << kInsnIsLoadPair)
61 #define ISSTORE (1ULL << kInsnIsStore)
62 #define ISSTOREPAIR (1ULL << kInsnIsStorePair)
63 #define ISATOMIC (1ULL << kInsnIsAtomic)
64 #define ISCALL (1ULL << kInsnIsCall)
65 #define ISTAILCALL (1ULL << kInsnIsTailCall)
66 #define ISCONVERSION (1ULL << kInsnIsConversion)
67 #define ISCONDDEF (1ULL << kInsnIsCondDef)
68 #define HASACQUIRE (1ULL << kInsnHasAcqure)
69 #define HASACQUIRERCPC (1ULL << kInsnHasAcqureRCpc)
70 #define HASLOACQUIRE (1ULL << kInsnHasLOAcqure)
71 #define HASRELEASE (1ULL << kInsnHasRelease)
72 #define HASLORELEASE (1ULL << kInsnHasLORelease)
73 #define CANTHROW (1ULL << kInsnCanThrow)
74 #define ISDMB (1ULL << kInsnIsDMB)
75 #define ISUNCONDBRANCH (1ULL << kInsnIsUnCondBr)
76 #define ISCONDBRANCH (1ULL << kInsnIsCondBr)
77 #define HASLOOP (1ULL << kInsnHasLoop)
78 #define ISVECTOR (1ULL << kInsnIsVectorOp)
79 #define ISBASICOP (1ULL << kInsnIsBinaryOp)
80 #define ISPHI (1ULL << kInsnIsPhi)
81 #define ISUNARYOP (1ULL << kInsnIsUnaryOp)
82 #define ISSHIFT (1ULL << kInsnIsShift)
83 #define INLINEASM (1ULL << kInsnInlineAsm)
84 #define SPINTRINSIC (1ULL << kInsnSpecialIntrisic)
85 #define ISNOP (1ULL << kInsnIsNop)
86 #define ISINTRINSIC (1ULL << kInsnIntrinsic)
87 constexpr maplebe::regno_t kInvalidRegNO = 0;
88 
89 /*
90  * ARM64 has 32 int registes and 32 FP registers.
91  * AMD64/X86_64 has 16 int registes, and 16 FP registers.
92  * In either case, the corresponding calling conventions use
93  * the smaller number of caller-saved registers.
94  * 64 bit is not large enough?
95  */
96 using CsrBitset = uint64_t;
97 
98 template <typename ParaType>
99 class ConstraintFunction {
100 public:
101     using cfPointer = bool (*)(ParaType);
CheckConstraint(cfPointer ccfunc,ParaType a)102     bool CheckConstraint(cfPointer ccfunc, ParaType a) const
103     {
104         return (*ccfunc)(a);
105     }
106 };
107 
108 /*
109  * abstract machine instruction
110  * a lower-level maple IR which is aimed to represent general machine instruction for extreme cpus
111  * 1. Support conversion between all types and registers
112  * 2. Support conversion between memory and registers
113  * 3. Support three address basic operations
114  *
115  */
116 namespace abstract {
117 #define DEFINE_MOP(op, ...) op,
118 enum AbstractMOP_t : maple::uint32 {
119 #include "abstract_mmir.def"
120     kMopLast
121 };
122 #undef DEFINE_MOP
123 }  // namespace abstract
124 
125 enum EncodeType : uint8 {
126     kMovImm,
127     kMovReg,
128     kAddSubExtendReg,
129     kAddSubImm,
130     kAddSubShiftImm,
131     kAddSubReg,
132     kAddSubShiftReg,
133     kBitfield,
134     kExtract,
135     kBranchImm,
136     kBranchReg,
137     kCompareBranch,
138     kCondCompareImm,
139     kCondCompareReg,
140     kConditionalSelect,
141     kDataProcess1Src,
142     kDataProcess2Src,
143     kDataProcess3Src,
144     kFloatIntConversions,
145     kFloatCompare,
146     kFloatDataProcessing1,
147     kFloatDataProcessing2,
148     kFloatDataProcessing3,
149     kFloatImm,
150     kFloatCondSelect,
151     kLoadStoreReg,
152     kLoadStoreAR,
153     kLoadExclusive,
154     kLoadExclusivePair,
155     kStoreExclusive,
156     kStoreExclusivePair,
157     kLoadPair,
158     kStorePair,
159     kLoadStoreFloat,
160     kLoadPairFloat,
161     kStorePairFloat,
162     kLoadLiteralReg,
163     kLogicalReg,
164     kLogicalImm,
165     kMoveWide,
166     kPCRelAddr,
167     kAddPCRelAddr,
168     kSystemInsn,
169     kTestBranch,
170     kCondBranch,
171     kUnknownEncodeType,
172 };
173 
174 struct InsnDesc {
InsnDescInsnDesc175     InsnDesc(MOperator op, std::vector<const OpndDesc *> opndmd, uint64 props, uint64 ltype, const std::string &inName,
176              const std::string &inFormat, uint32 anum)
177         : opc(op),
178           opndMD(opndmd),
179           properties(props),
180           latencyType(ltype),
181           name(inName),
182           format(inFormat),
183           atomicNum(anum) {};
184 
185     // for hard-coded machine description.
InsnDescInsnDesc186     InsnDesc(MOperator op, std::vector<const OpndDesc *> opndmd, uint64 props, uint64 ltype, const std::string &inName,
187              const std::string &inFormat, uint32 anum, std::function<bool(int64)> vFunc)
188         : opc(op),
189           opndMD(opndmd),
190           properties(props),
191           latencyType(ltype),
192           name(inName),
193           format(inFormat),
194           atomicNum(anum),
195           validFunc(vFunc) {};
196 
197     // for aarch64 assemble
InsnDescInsnDesc198     InsnDesc(MOperator op, std::vector<const OpndDesc *> opndmd, uint64 props, uint64 ltype, const std::string &inName,
199              const std::string &inFormat, uint32 anum, std::function<bool(int64)> vFunc, EncodeType type, uint32 encode)
200         : opc(op),
201           opndMD(opndmd),
202           properties(props),
203           latencyType(ltype),
204           name(inName),
205           format(inFormat),
206           atomicNum(anum),
207           validFunc(vFunc),
208           encodeType(type),
209           mopEncode(encode) {};
210 
211     // for aarch64 assemble
InsnDescInsnDesc212     InsnDesc(MOperator op, std::vector<const OpndDesc *> opndmd, uint64 props, uint64 ltype, const std::string &inName,
213              const std::string &inFormat, uint32 anum, EncodeType type, uint32 encode)
214         : opc(op),
215           opndMD(opndmd),
216           properties(props),
217           latencyType(ltype),
218           name(inName),
219           format(inFormat),
220           atomicNum(anum),
221           encodeType(type),
222           mopEncode(encode) {};
223 
224     MOperator opc;
225     std::vector<const OpndDesc *> opndMD;
226     uint64 properties;
227     uint32 latencyType;
228     const std::string name;
229     const std::string format;
230     uint32 atomicNum;                               /* indicate how many asm instructions it will emit. */
231     std::function<bool(int64)> validFunc = nullptr; /* If insn has immOperand, this function needs to be implemented. */
232     EncodeType encodeType = kUnknownEncodeType;
233     uint32 mopEncode = 0x00000000;
234 
235     bool IsSame(const InsnDesc &left, std::function<bool(const InsnDesc &left, const InsnDesc &right)> cmp) const;
236 
IsCallInsnDesc237     bool IsCall() const
238     {
239         return (properties & ISCALL) != 0;
240     }
IsTailCallInsnDesc241     bool IsTailCall() const
242     {
243         return properties & ISTAILCALL;
244     }
IsPhiInsnDesc245     bool IsPhi() const
246     {
247         return (properties & ISPHI) != 0;
248     }
IsPhysicalInsnInsnDesc249     bool IsPhysicalInsn() const
250     {
251         return (properties & ISABSTRACT) == 0;
252     }
IsStoreInsnDesc253     bool IsStore() const
254     {
255         return (properties & ISSTORE) != 0;
256     }
IsLoadInsnDesc257     bool IsLoad() const
258     {
259         return (properties & ISLOAD) != 0;
260     }
IsConversionInsnDesc261     bool IsConversion() const
262     {
263         return (properties & ISCONVERSION) != 0;
264     }
IsLoadPairInsnDesc265     bool IsLoadPair() const
266     {
267         return (properties & (ISLOADPAIR)) != 0;
268     }
IsStorePairInsnDesc269     bool IsStorePair() const
270     {
271         return (properties & (ISSTOREPAIR)) != 0;
272     }
IsLoadStorePairInsnDesc273     bool IsLoadStorePair() const
274     {
275         return (properties & (ISLOADPAIR | ISSTOREPAIR)) != 0;
276     }
IsMoveInsnDesc277     bool IsMove() const
278     {
279         return (properties & ISMOVE) != 0;
280     }
IsDMBInsnDesc281     bool IsDMB() const
282     {
283         return (properties & (ISDMB)) != 0;
284     }
IsBasicOpInsnDesc285     bool IsBasicOp() const
286     {
287         return (properties & ISBASICOP) != 0;
288     }
IsCondBranchInsnDesc289     bool IsCondBranch() const
290     {
291         return (properties & (ISCONDBRANCH)) != 0;
292     }
IsUnCondBranchInsnDesc293     bool IsUnCondBranch() const
294     {
295         return (properties & (ISUNCONDBRANCH)) != 0;
296     }
IsAtomicInsnDesc297     bool IsAtomic() const
298     {
299         return (properties & ISATOMIC) != 0;
300     }
301 
IsCondDefInsnDesc302     bool IsCondDef() const
303     {
304         return (properties & ISCONDDEF) != 0;
305     }
306 
IsVectorOpInsnDesc307     bool IsVectorOp() const
308     {
309         return (properties & ISVECTOR) != 0;
310     }
311 
IsVolatileInsnDesc312     bool IsVolatile() const
313     {
314         return ((properties & HASRELEASE) != 0) || ((properties & HASACQUIRE) != 0);
315     }
316 
IsMemAccessBarInsnDesc317     bool IsMemAccessBar() const
318     {
319         return (properties & (HASRELEASE | HASACQUIRE | HASACQUIRERCPC | HASLOACQUIRE | HASLORELEASE)) != 0;
320     }
321 
IsMemAccessInsnDesc322     bool IsMemAccess() const
323     {
324         return (properties & (ISLOAD | ISSTORE | ISLOADPAIR | ISSTOREPAIR)) != 0;
325     }
326 
IsBranchInsnDesc327     bool IsBranch() const
328     {
329         return (properties & (ISCONDBRANCH | ISUNCONDBRANCH)) != 0;
330     }
331 
HasLoopInsnDesc332     bool HasLoop() const
333     {
334         return (properties & HASLOOP) != 0;
335     }
336 
CanThrowInsnDesc337     bool CanThrow() const
338     {
339         return (properties & CANTHROW) != 0;
340     }
341 
IsInlineAsmInsnDesc342     bool IsInlineAsm() const
343     {
344         return properties & INLINEASM;
345     }
346 
IsSpecialIntrinsicInsnDesc347     bool IsSpecialIntrinsic() const
348     {
349         return properties & SPINTRINSIC;
350     }
351 
IsIntrinsicInsnDesc352     bool IsIntrinsic() const
353     {
354         return properties & ISINTRINSIC;
355     }
356 
GetOpcInsnDesc357     MOperator GetOpc() const
358     {
359         return opc;
360     }
361 
GetOpndDesInsnDesc362     const OpndDesc *GetOpndDes(size_t index) const
363     {
364         return opndMD[index];
365     }
366 
GetOpndMDLengthInsnDesc367     uint32 GetOpndMDLength() const
368     {
369         return opndMD.size();
370     }
371 
GetOperandSizeInsnDesc372     uint32 GetOperandSize() const
373     {
374         if (properties & (ISLOAD | ISSTORE)) {
375             /* use memory operand */
376             return GetOpndDes(1)->GetSize();
377         }
378         /* use dest operand */
379         return GetOpndDes(0)->GetSize();
380     }
381 
Is64BitInsnDesc382     bool Is64Bit() const
383     {
384         return GetOperandSize() == k64BitSize;
385     }
386 
IsValidImmOpndInsnDesc387     bool IsValidImmOpnd(int64 val) const
388     {
389         if (!validFunc) {
390             return true;
391         }
392         return validFunc(val);
393     }
394 
GetLatencyTypeInsnDesc395     uint32 GetLatencyType() const
396     {
397         return latencyType;
398     }
399 
IsUnaryOpInsnDesc400     bool IsUnaryOp() const
401     {
402         return (properties & ISUNARYOP) != 0;
403     }
404 
IsShiftInsnDesc405     bool IsShift() const
406     {
407         return (properties & ISSHIFT) != 0;
408     }
409 
GetNameInsnDesc410     const std::string &GetName() const
411     {
412         return name;
413     }
414 
GetFormatInsnDesc415     const std::string &GetFormat() const
416     {
417         return format;
418     }
419 
GetAtomicNumInsnDesc420     uint32 GetAtomicNum() const
421     {
422         return atomicNum;
423     }
424 
GetEncodeTypeInsnDesc425     EncodeType GetEncodeType() const
426     {
427         return encodeType;
428     }
429 
GetMopEncodeInsnDesc430     uint32 GetMopEncode() const
431     {
432         return mopEncode;
433     }
434 
GetAbstractIdInsnDesc435     static const InsnDesc &GetAbstractId(MOperator opc)
436     {
437         DEBUG_ASSERT(opc < abstract::kMopLast, "op must be lower than kMopLast");
438         return abstractId[opc];
439     }
440 
441     static const InsnDesc abstractId[abstract::kMopLast];
442 };
443 
444 enum RegAddress : uint32 { kRegHigh = 0x4, kRegLow = 0x8 };
445 constexpr uint32 kMemLow12 = 0x10;
446 constexpr uint32 kLiteralLow12 = kMemLow12;
447 constexpr uint32 kPreInc = 0x20;
448 constexpr uint32 kPostInc = 0x40;
449 constexpr uint32 kLoadLiteral = 0x80;
450 
451 enum BitIndex : maple::uint8 {
452     k8BitIndex = 0,
453     k16BitIndex,
454     k32BitIndex,
455     k64BitIndex,
456     kBitIndexEnd,
457 };
458 
GetBitIndex(uint32 bitSize)459 static inline BitIndex GetBitIndex(uint32 bitSize)
460 {
461     switch (bitSize) {
462         case k8BitSize:
463             return k8BitIndex;
464         case k16BitSize:
465             return k16BitIndex;
466         case k32BitSize:
467             return k32BitIndex;
468         case k64BitSize:
469             return k64BitIndex;
470         default:
471             CHECK_FATAL(false, "NIY, Not support size");
472     }
473 }
474 } /* namespace maplebe */
475 
476 #endif /* MAPLEBE_INCLUDE_CG_ISA_H */
477