• 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_AARCH64_AARCH64_ISA_H
17 #define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_ISA_H
18 
19 #include "isa.h"
20 
21 #define DEFINE_MOP(op, ...) op,
22 enum AArch64MopT : maple::uint32 {
23 #include "abstract_mmir.def"
24 #include "aarch64_md.def"
25     kMopLast
26 };
27 #undef DEFINE_MOP
28 
29 namespace maplebe {
30 /*
31  * ARM Architecture Reference Manual (for ARMv8)
32  * D1.8.2
33  */
34 constexpr int kAarch64StackPtrAlignment = 16;
35 
36 constexpr int32 kAarch64OffsetAlign = 8;
37 constexpr uint32 kAarch64IntregBytelen = 8; /* 64-bit */
38 constexpr uint32 kAarch64FpregBytelen = 8;  /* only lower 64 bits are used */
39 constexpr int kAarch64SizeOfFplr = 16;
40 
41 enum StpLdpImmBound : int {
42     kStpLdpImm64LowerBound = -512,
43     kStpLdpImm64UpperBound = 504,
44     kStpLdpImm32LowerBound = -256,
45     kStpLdpImm32UpperBound = 252
46 };
47 
48 enum StrLdrPerPostBound : int64 { kStrLdrPerPostLowerBound = -256, kStrLdrPerPostUpperBound = 255 };
49 
50 constexpr int64 kStrAllLdrAllImmLowerBound = 0;
51 enum StrLdrImmUpperBound : int64 {
52     kStrLdrImm32UpperBound = 16380, /* must be a multiple of 4 */
53     kStrLdrImm64UpperBound = 32760, /* must be a multiple of 8 */
54     kStrbLdrbImmUpperBound = 4095,
55     kStrhLdrhImmUpperBound = 8190
56 };
57 
58 /*
59  * ARM Compiler armasm User Guide version 6.6.
60  * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0473j/deb1353594352617.html
61  * (retrieved on 3/24/2017)
62  *
63  * $ 4.1 Registers in AArch64 state
64  * ...When you use the 32-bit form of an instruction, the upper
65  * 32 bits of the source registers are ignored and
66  * the upper 32 bits of the destination register are set to zero.
67  * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
68  *
69  * There is no register named W31 or X31.
70  * Depending on the instruction, register 31 is either the stack
71  * pointer or the zero register. When used as the stack pointer,
72  * you refer to it as "SP". When used as the zero register, you refer
73  * to it as WZR in a 32-bit context or XZR in a 64-bit context.
74  * The zero register returns 0 when read and discards data when
75  * written (e.g., when setting the status register for testing).
76  */
77 enum AArch64reg : uint32 {
78     kRinvalid = kInvalidRegNO,
79 /* integer registers */
80 #define INT_REG(ID, PREF32, PREF64, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) R##ID,
81 #define INT_REG_ALIAS(ALIAS, ID, PREF32, PREF64)
82 #include "aarch64_int_regs.def"
83 #undef INT_REG
84 #undef INT_REG_ALIAS
85 /* fp-simd registers */
86 #define FP_SIMD_REG(ID, PV, P8, P16, P32, P64, P128, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill) V##ID,
87 #define FP_SIMD_REG_ALIAS(ID)
88 #include "aarch64_fp_simd_regs.def"
89 #undef FP_SIMD_REG
90 #undef FP_SIMD_REG_ALIAS
91     kMaxRegNum,
92     kRFLAG,
93     kAllRegNum,
94 /* alias */
95 #define INT_REG(ID, PREF32, PREF64, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill)
96 #define INT_REG_ALIAS(ALIAS, ID, PREF32, PREF64) R##ALIAS = R##ID,
97 #include "aarch64_int_regs.def"
98 #undef INT_REG
99 #undef INT_REG_ALIAS
100 #define FP_SIMD_REG(ID, PV, P8, P16, P32, P64, P128, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill)
101 #define FP_SIMD_REG_ALIAS(ID) S##ID = V##ID,
102 #include "aarch64_fp_simd_regs.def"
103 #undef FP_SIMD_REG
104 #undef FP_SIMD_REG_ALIAS
105 #define FP_SIMD_REG(ID, PV, P8, P16, P32, P64, P128, canBeAssigned, isCalleeSave, isParam, isSpill, isExtraSpill)
106 #define FP_SIMD_REG_ALIAS(ID) D##ID = V##ID,
107 #include "aarch64_fp_simd_regs.def"
108 #undef FP_SIMD_REG
109 #undef FP_SIMD_REG_ALIAS
110 };
111 
112 class Insn;
113 
114 namespace AArch64isa {
IsGPRegister(AArch64reg r)115 static inline bool IsGPRegister(AArch64reg r)
116 {
117     return R0 <= r && r <= RZR;
118 }
119 
IsFPSIMDRegister(AArch64reg r)120 static inline bool IsFPSIMDRegister(AArch64reg r)
121 {
122     return V0 <= r && r <= V31;
123 }
124 
IsPhysicalRegister(regno_t r)125 static inline bool IsPhysicalRegister(regno_t r)
126 {
127     return r < kMaxRegNum;
128 }
129 
GetRegType(AArch64reg r)130 static inline RegType GetRegType(AArch64reg r)
131 {
132     if (IsGPRegister(r)) {
133         return kRegTyInt;
134     }
135     if (IsFPSIMDRegister(r)) {
136         return kRegTyFloat;
137     }
138     DEBUG_ASSERT(false, "No suitable register type to return?");
139     return kRegTyUndef;
140 }
141 
IsPseudoInstruction(MOperator mOp)142 static inline bool IsPseudoInstruction(MOperator mOp)
143 {
144     return (mOp >= MOP_pseudo_param_def_x && mOp <= MOP_pseudo_eh_def_x);
145 }
146 
147 /*
148  * Precondition: The given insn is a jump instruction.
149  * Get the jump target label operand index from the given instruction.
150  * Note: MOP_xbr is a jump instruction, but the target is unknown at compile time,
151  * because a register instead of label. So we don't take it as a branching instruction.
152  * However for special long range branch patch, the label is installed in this case.
153  */
154 uint32 GetJumpTargetIdx(const Insn &insn);
155 
156 bool IsSub(const Insn &insn);
157 
158 MOperator GetMopSub2Subs(const Insn &insn);
159 
160 MOperator FlipConditionOp(MOperator flippedOp);
161 
162 // Function: for immediate verification, memopnd ofstvalue is returned from opnd input.
163 // It's worth noting that 0 will be returned when kBOR memopnd is input.
164 int64 GetMemOpndOffsetValue(Operand *o);
165 
166 int32 GetTail0BitNum(int64 val);
167 
168 int32 GetHead0BitNum(int64 val);
169 
GetNextOffsetCalleeSaved(int & offset)170 inline void GetNextOffsetCalleeSaved(int &offset)
171 {
172     offset += (kAarch64IntregBytelen  << 1);
173 }
174 } /* namespace AArch64isa */
175 
176 /*
177  * We save callee-saved registers from lower stack area to upper stack area.
178  * If possible, we store a pair of registers (int/int and fp/fp) in the stack.
179  * The Stack Pointer has to be aligned at 16-byte boundary.
180  * On AArch64, kIntregBytelen == 8 (see the above)
181  */
182 
183 MOperator GetMopPair(MOperator mop, bool isIncludeStrbStrh);
184 } /* namespace maplebe */
185 
186 #endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_ISA_H */
187