• 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 // For verify & split insn
25 #define VERIFY_INSN(INSN) (INSN)->VerifySelf()
26 #define SPLIT_INSN(INSN, FUNC) \
27     (INSN)->SplitSelf((FUNC)->IsAfterRegAlloc(), (FUNC)->GetInsnBuilder(), (FUNC)->GetOpndBuilder())
28 
29 // circular dependency exists, no other choice
30 class Insn;
31 class InsnBuilder;
32 class OperandBuilder;
33 
34 enum MopProperty : maple::uint8 {
35     kInsnIsAbstract,
36     kInsnIsMove,
37     kInsnIsLoad,
38     kInsnIsLoadPair,
39     kInsnIsStore,
40     kInsnIsStorePair,
41     kInsnIsLoadAddress,
42     kInsnIsAtomic,
43     kInsnIsCall,
44     kInsnIsSpecialCall,
45     kInsnIsTailCall,
46     kInsnIsConversion,
47     kInsnIsCondDef,
48     kInsnHasAcqure,
49     kInsnHasAcqureRCpc,
50     kInsnHasLOAcqure,
51     kInsnHasRelease,
52     kInsnHasLORelease,
53     kInsnCanThrow,
54     kInsnIsDMB,
55     kInsnIsUnCondBr,
56     kInsnIsCondBr,
57     kInsnHasLoop,
58     kInsnIsBinaryOp,
59     kInsnIsPhi,
60     kInsnIsUnaryOp,
61     kInsnIsShift,
62     kInsnInlineAsm,
63     kInsnSpecialIntrisic,
64     kInsnIsNop,
65     kInsnIntrinsic,
66     kInsnIsBreakPoint,
67 };
68 using regno_t = uint32_t;
69 #define ISABSTRACT 1ULL
70 #define ISMOVE (1ULL << kInsnIsMove)
71 #define ISLOAD (1ULL << kInsnIsLoad)
72 #define ISLOADPAIR (1ULL << kInsnIsLoadPair)
73 #define ISSTORE (1ULL << kInsnIsStore)
74 #define ISSTOREPAIR (1ULL << kInsnIsStorePair)
75 #define ISLOADADDR (1ULL << kInsnIsLoadAddress)
76 #define ISATOMIC (1ULL << kInsnIsAtomic)
77 #define ISCALL (1ULL << kInsnIsCall)
78 #define ISSPCALL (1ULL << kInsnIsSpecialCall)
79 #define ISTAILCALL (1ULL << kInsnIsTailCall)
80 #define ISCONVERSION (1ULL << kInsnIsConversion)
81 #define ISCONDDEF (1ULL << kInsnIsCondDef)
82 #define HASACQUIRE (1ULL << kInsnHasAcqure)
83 #define HASACQUIRERCPC (1ULL << kInsnHasAcqureRCpc)
84 #define HASLOACQUIRE (1ULL << kInsnHasLOAcqure)
85 #define HASRELEASE (1ULL << kInsnHasRelease)
86 #define HASLORELEASE (1ULL << kInsnHasLORelease)
87 #define CANTHROW (1ULL << kInsnCanThrow)
88 #define ISDMB (1ULL << kInsnIsDMB)
89 #define ISUNCONDBRANCH (1ULL << kInsnIsUnCondBr)
90 #define ISCONDBRANCH (1ULL << kInsnIsCondBr)
91 #define HASLOOP (1ULL << kInsnHasLoop)
92 #define ISBASICOP (1ULL << kInsnIsBinaryOp)
93 #define ISPHI (1ULL << kInsnIsPhi)
94 #define ISUNARYOP (1ULL << kInsnIsUnaryOp)
95 #define ISSHIFT (1ULL << kInsnIsShift)
96 #define INLINEASM (1ULL << kInsnInlineAsm)
97 #define SPINTRINSIC (1ULL << kInsnSpecialIntrisic)
98 #define ISNOP (1ULL << kInsnIsNop)
99 #define ISINTRINSIC (1ULL << kInsnIntrinsic)
100 #define ISBREAKPOINT (1ULL << kInsnIsBreakPoint)
101 constexpr maplebe::regno_t kInvalidRegNO = 0;
102 
103 /*
104  * ARM64 has 32 int registes and 32 FP registers.
105  * AMD64/X86_64 has 16 int registes, and 16 FP registers.
106  * In either case, the corresponding calling conventions use
107  * the smaller number of caller-saved registers.
108  * 64 bit is not large enough?
109  */
110 using CsrBitset = uint64_t;
111 
112 template <typename ParaType>
113 class ConstraintFunction {
114 public:
115     using CfPointer = bool (*)(ParaType);
CheckConstraint(CfPointer ccfunc,ParaType a)116     bool CheckConstraint(CfPointer ccfunc, ParaType a) const
117     {
118         return (*ccfunc)(a);
119     }
120 };
121 
122 /*
123  * abstract machine instruction
124  * a lower-level maple IR which is aimed to represent general machine instruction for extreme cpus
125  * 1. Support conversion between all types and registers
126  * 2. Support conversion between memory and registers
127  * 3. Support three address basic operations
128  *
129  */
130 namespace abstract {
131 #define DEFINE_MOP(op, ...) op,
132 enum AbstractMOP_t : maple::uint32 {
133 #include "abstract_mmir.def"
134     kMopLast
135 };
136 #undef DEFINE_MOP
137 }  // namespace abstract
138 
139 enum EncodeType : uint8 {
140     kMovImm,
141     kMovReg,
142     kAddSubExtendReg,
143     kAddSubImm,
144     kAddSubShiftImm,
145     kAddSubReg,
146     kAddSubShiftReg,
147     kBitfield,
148     kExtract,
149     kBranchImm,
150     kBranchReg,
151     kCompareBranch,
152     kCondCompareImm,
153     kCondCompareReg,
154     kConditionalSelect,
155     kDataProcess1Src,
156     kDataProcess2Src,
157     kDataProcess3Src,
158     kFloatIntConversions,
159     kFloatCompare,
160     kFloatDataProcessing1,
161     kFloatDataProcessing2,
162     kFloatDataProcessing3,
163     kFloatImm,
164     kFloatCondSelect,
165     kLoadStoreReg,
166     kLoadStoreAR,
167     kLoadExclusive,
168     kLoadExclusivePair,
169     kStoreExclusive,
170     kStoreExclusivePair,
171     kLoadPair,
172     kStorePair,
173     kLoadStoreFloat,
174     kLoadPairFloat,
175     kStorePairFloat,
176     kLoadLiteralReg,
177     kLogicalReg,
178     kLogicalImm,
179     kMoveWide,
180     kPCRelAddr,
181     kAddPCRelAddr,
182     kBrkInsn,
183     kSystemInsn,
184     kTestBranch,
185     kCondBranch,
186     kUnknownEncodeType,
187 };
188 
189 struct InsnDesc {
190     using ImmValidFunc = std::function<bool(const MapleVector<Operand *>)>;
191     using SplitFunc = std::function<void(Insn *, bool, InsnBuilder *, OperandBuilder *)>;
192 
InsnDescInsnDesc193     InsnDesc(MOperator op, std::vector<const OpndDesc *> opndmd, uint64 props, uint64 ltype, const std::string &inName,
194              const std::string &inFormat, uint32 anum)
195         : opc(op),
196           opndMD(opndmd),
197           properties(props),
198           latencyType(ltype),
199           name(inName),
200           format(inFormat),
201           atomicNum(anum) {};
202 
203     // for hard-coded machine description.
InsnDescInsnDesc204     InsnDesc(MOperator op, std::vector<const OpndDesc *> opndmd, uint64 props, uint64 ltype, const std::string &inName,
205              const std::string &inFormat, uint32 anum, const ImmValidFunc &vFunc, const SplitFunc &sFunc)
206         : opc(op),
207           opndMD(opndmd),
208           properties(props),
209           latencyType(ltype),
210           name(inName),
211           format(inFormat),
212           atomicNum(anum),
213           validFunc(vFunc),
214           splitFunc(sFunc) {};
215 
216     // for hard-coded machine description.
InsnDescInsnDesc217     InsnDesc(MOperator op, std::vector<const OpndDesc *> opndmd, uint64 props, uint64 ltype, const std::string &inName,
218              const std::string &inFormat, uint32 anum, const ImmValidFunc &vFunc, const SplitFunc &sFunc,
219              EncodeType type, uint32 encode)
220         : opc(op),
221           opndMD(opndmd),
222           properties(props),
223           latencyType(ltype),
224           name(inName),
225           format(inFormat),
226           atomicNum(anum),
227           validFunc(vFunc),
228           splitFunc(sFunc),
229           encodeType(type),
230           mopEncode(encode) {};
231 
232     // for aarch64 assemble
InsnDescInsnDesc233     InsnDesc(MOperator op, std::vector<const OpndDesc *> opndmd, uint64 props, uint64 ltype, const std::string &inName,
234              const std::string &inFormat, uint32 anum, const ImmValidFunc &vFunc, EncodeType type, uint32 encode)
235         : opc(op),
236           opndMD(opndmd),
237           properties(props),
238           latencyType(ltype),
239           name(inName),
240           format(inFormat),
241           atomicNum(anum),
242           validFunc(vFunc),
243           encodeType(type),
244           mopEncode(encode) {};
245 
246     // for aarch64 assemble
InsnDescInsnDesc247     InsnDesc(MOperator op, std::vector<const OpndDesc *> opndmd, uint64 props, uint64 ltype, const std::string &inName,
248              const std::string &inFormat, uint32 anum, EncodeType type, uint32 encode)
249         : opc(op),
250           opndMD(opndmd),
251           properties(props),
252           latencyType(ltype),
253           name(inName),
254           format(inFormat),
255           atomicNum(anum),
256           encodeType(type),
257           mopEncode(encode) {};
258 
259     MOperator opc;
260     std::vector<const OpndDesc *> opndMD;
261     uint64 properties;
262     uint32 latencyType;
263     const std::string name;
264     const std::string format;
265     uint32 atomicNum;                 /* indicate how many asm instructions it will emit. */
266     ImmValidFunc validFunc = nullptr; /* If insn has immOperand, this function needs to be implemented. */
267     // If insn needs to be split, this function needs to be implemented.
268     SplitFunc splitFunc = nullptr;
269     EncodeType encodeType = kUnknownEncodeType;
270     uint32 mopEncode = 0x00000000;
271 
272     bool IsSame(const InsnDesc &left, std::function<bool(const InsnDesc &left, const InsnDesc &right)> cmp) const;
273 
IsCallInsnDesc274     bool IsCall() const
275     {
276         return (properties & ISCALL) != 0;
277     }
278     // call insn does not obey standard call procedure!
IsSpecialCallInsnDesc279     bool IsSpecialCall() const
280     {
281         return (properties & ISSPCALL) != 0;
282     }
IsTailCallInsnDesc283     bool IsTailCall() const
284     {
285         return properties & ISTAILCALL;
286     }
IsPhiInsnDesc287     bool IsPhi() const
288     {
289         return (properties & ISPHI) != 0;
290     }
IsPhysicalInsnInsnDesc291     bool IsPhysicalInsn() const
292     {
293         return (properties & ISABSTRACT) == 0;
294     }
IsStoreInsnDesc295     bool IsStore() const
296     {
297         return (properties & ISSTORE) != 0;
298     }
IsLoadInsnDesc299     bool IsLoad() const
300     {
301         return (properties & ISLOAD) != 0;
302     }
IsConversionInsnDesc303     bool IsConversion() const
304     {
305         return (properties & ISCONVERSION) != 0;
306     }
IsLoadPairInsnDesc307     bool IsLoadPair() const
308     {
309         return (properties & (ISLOADPAIR)) != 0;
310     }
IsStorePairInsnDesc311     bool IsStorePair() const
312     {
313         return (properties & (ISSTOREPAIR)) != 0;
314     }
IsLoadStorePairInsnDesc315     bool IsLoadStorePair() const
316     {
317         return (properties & (ISLOADPAIR | ISSTOREPAIR)) != 0;
318     }
IsMoveInsnDesc319     bool IsMove() const
320     {
321         return (properties & ISMOVE) != 0;
322     }
IsDMBInsnDesc323     bool IsDMB() const
324     {
325         return (properties & (ISDMB)) != 0;
326     }
IsBasicOpInsnDesc327     bool IsBasicOp() const
328     {
329         return (properties & ISBASICOP) != 0;
330     }
IsCondBranchInsnDesc331     bool IsCondBranch() const
332     {
333         return (properties & (ISCONDBRANCH)) != 0;
334     }
IsUnCondBranchInsnDesc335     bool IsUnCondBranch() const
336     {
337         return (properties & (ISUNCONDBRANCH)) != 0;
338     }
IsLoadAddressInsnDesc339     bool IsLoadAddress() const
340     {
341         return (properties & (ISLOADADDR)) != 0;
342     }
IsAtomicInsnDesc343     bool IsAtomic() const
344     {
345         return (properties & ISATOMIC) != 0;
346     }
347 
IsCondDefInsnDesc348     bool IsCondDef() const
349     {
350         return (properties & ISCONDDEF) != 0;
351     }
352 
IsVolatileInsnDesc353     bool IsVolatile() const
354     {
355         return ((properties & HASRELEASE) != 0) || ((properties & HASACQUIRE) != 0);
356     }
357 
IsMemAccessBarInsnDesc358     bool IsMemAccessBar() const
359     {
360         return (properties & (HASRELEASE | HASACQUIRE | HASACQUIRERCPC | HASLOACQUIRE | HASLORELEASE)) != 0;
361     }
362 
IsMemAccessInsnDesc363     bool IsMemAccess() const
364     {
365         return (properties & (ISLOAD | ISSTORE | ISLOADPAIR | ISSTOREPAIR)) != 0;
366     }
367 
IsBranchInsnDesc368     bool IsBranch() const
369     {
370         return (properties & (ISCONDBRANCH | ISUNCONDBRANCH)) != 0;
371     }
372 
HasLoopInsnDesc373     bool HasLoop() const
374     {
375         return (properties & HASLOOP) != 0;
376     }
377 
CanThrowInsnDesc378     bool CanThrow() const
379     {
380         return (properties & CANTHROW) != 0;
381     }
382 
IsInlineAsmInsnDesc383     bool IsInlineAsm() const
384     {
385         return properties & INLINEASM;
386     }
387 
IsSpecialIntrinsicInsnDesc388     bool IsSpecialIntrinsic() const
389     {
390         return properties & SPINTRINSIC;
391     }
392 
IsIntrinsicInsnDesc393     bool IsIntrinsic() const
394     {
395         return properties & ISINTRINSIC;
396     }
397 
GetOpcInsnDesc398     MOperator GetOpc() const
399     {
400         return opc;
401     }
402 
VerifyInsnDesc403     bool Verify(const MapleVector<Operand *> &opnds) const
404     {
405         if (!validFunc) {
406             return true;
407         }
408         if (opnds.size() != opndMD.size()) {
409             CHECK_FATAL_FALSE("The size of opnds is wrong.");
410         }
411         return validFunc(opnds);
412     }
413 
SplitInsnDesc414     void Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) const
415     {
416         if (!splitFunc) {
417             return;
418         }
419         splitFunc(insn, isAfterRegAlloc, insnBuilder, opndBuilder);
420     }
421 
GetOpndDesInsnDesc422     const OpndDesc *GetOpndDes(size_t index) const
423     {
424         return opndMD[index];
425     }
426 
GetOpndMDLengthInsnDesc427     uint32 GetOpndMDLength() const
428     {
429         return opndMD.size();
430     }
431 
GetOperandSizeInsnDesc432     uint32 GetOperandSize() const
433     {
434         if (properties & (ISLOAD | ISSTORE)) {
435             /* use memory operand */
436             return GetOpndDes(1)->GetSize();
437         }
438         /* use dest operand */
439         return GetOpndDes(0)->GetSize();
440     }
441 
Is64BitInsnDesc442     bool Is64Bit() const
443     {
444         return GetOperandSize() == k64BitSize;
445     }
446 
GetLatencyTypeInsnDesc447     uint32 GetLatencyType() const
448     {
449         return latencyType;
450     }
451 
IsUnaryOpInsnDesc452     bool IsUnaryOp() const
453     {
454         return (properties & ISUNARYOP) != 0;
455     }
456 
IsShiftInsnDesc457     bool IsShift() const
458     {
459         return (properties & ISSHIFT) != 0;
460     }
461 
GetNameInsnDesc462     const std::string &GetName() const
463     {
464         return name;
465     }
466 
GetFormatInsnDesc467     const std::string &GetFormat() const
468     {
469         return format;
470     }
471 
GetAtomicNumInsnDesc472     uint32 GetAtomicNum() const
473     {
474         return atomicNum;
475     }
476 
IsBreakPointInsnDesc477     bool IsBreakPoint() const
478     {
479         return (properties & ISBREAKPOINT) != 0;
480     }
481 
GetEncodeTypeInsnDesc482     EncodeType GetEncodeType() const
483     {
484         return encodeType;
485     }
486 
GetMopEncodeInsnDesc487     uint32 GetMopEncode() const
488     {
489         return mopEncode;
490     }
491 
GetAbstractIdInsnDesc492     static const InsnDesc &GetAbstractId(MOperator opc)
493     {
494         DEBUG_ASSERT(opc < abstract::kMopLast, "op must be lower than kMopLast");
495         return abstractId[opc];
496     }
497 
498     static const InsnDesc abstractId[abstract::kMopLast];
499 };
500 
501 enum RegAddress : uint32 { kRegHigh = 0x4, kRegLow = 0x8 };
502 constexpr uint32 kMemLow12 = 0x10;
503 constexpr uint32 kLiteralLow12 = kMemLow12;
504 constexpr uint32 kPreInc = 0x20;
505 constexpr uint32 kPostInc = 0x40;
506 constexpr uint32 kLoadLiteral = 0x80;
507 
508 enum BitIndex : maple::uint8 {
509     k8BitIndex = 0,
510     k16BitIndex,
511     k32BitIndex,
512     k64BitIndex,
513     kBitIndexEnd,
514 };
515 
GetBitIndex(uint32 bitSize)516 static inline BitIndex GetBitIndex(uint32 bitSize)
517 {
518     switch (bitSize) {
519         case k8BitSize:
520             return k8BitIndex;
521         case k16BitSize:
522             return k16BitIndex;
523         case k32BitSize:
524             return k32BitIndex;
525         case k64BitSize:
526             return k64BitIndex;
527         default:
528             CHECK_FATAL(false, "NIY, Not support size");
529     }
530 }
531 } /* namespace maplebe */
532 
533 #endif /* MAPLEBE_INCLUDE_CG_ISA_H */
534