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 #include "aarch64_isa.h"
17 #include "insn.h"
18
19 namespace maplebe {
20 /*
21 * Get the ldp/stp corresponding to ldr/str
22 * mop : a ldr or str machine operator
23 */
GetMopPair(MOperator mop,bool isIncludeStrbStrh)24 MOperator GetMopPair(MOperator mop, bool isIncludeStrbStrh)
25 {
26 switch (mop) {
27 case MOP_xldr:
28 return MOP_xldp;
29 case MOP_wldr:
30 return MOP_wldp;
31 case MOP_xstr:
32 return MOP_xstp;
33 case MOP_wstr:
34 return MOP_wstp;
35 case MOP_dldr:
36 return MOP_dldp;
37 case MOP_qldr:
38 return MOP_qldp;
39 case MOP_sldr:
40 return MOP_sldp;
41 case MOP_dstr:
42 return MOP_dstp;
43 case MOP_sstr:
44 return MOP_sstp;
45 case MOP_qstr:
46 return MOP_qstp;
47 case MOP_wstrb:
48 return isIncludeStrbStrh ? MOP_wstrh : MOP_undef;
49 case MOP_wstrh:
50 return isIncludeStrbStrh ? MOP_wstr : MOP_undef;
51 default:
52 DEBUG_ASSERT(false, "should not run here");
53 return MOP_undef;
54 }
55 }
56 namespace AArch64isa {
FlipConditionOp(MOperator flippedOp)57 MOperator FlipConditionOp(MOperator flippedOp)
58 {
59 switch (flippedOp) {
60 case AArch64MopT::MOP_beq:
61 return AArch64MopT::MOP_bne;
62 case AArch64MopT::MOP_bge:
63 return AArch64MopT::MOP_blt;
64 case AArch64MopT::MOP_bgt:
65 return AArch64MopT::MOP_ble;
66 case AArch64MopT::MOP_bhi:
67 return AArch64MopT::MOP_bls;
68 case AArch64MopT::MOP_bhs:
69 return AArch64MopT::MOP_blo;
70 case AArch64MopT::MOP_ble:
71 return AArch64MopT::MOP_bgt;
72 case AArch64MopT::MOP_blo:
73 return AArch64MopT::MOP_bhs;
74 case AArch64MopT::MOP_bls:
75 return AArch64MopT::MOP_bhi;
76 case AArch64MopT::MOP_blt:
77 return AArch64MopT::MOP_bge;
78 case AArch64MopT::MOP_bne:
79 return AArch64MopT::MOP_beq;
80 case AArch64MopT::MOP_bpl:
81 return AArch64MopT::MOP_bmi;
82 case AArch64MopT::MOP_xcbnz:
83 return AArch64MopT::MOP_xcbz;
84 case AArch64MopT::MOP_wcbnz:
85 return AArch64MopT::MOP_wcbz;
86 case AArch64MopT::MOP_xcbz:
87 return AArch64MopT::MOP_xcbnz;
88 case AArch64MopT::MOP_wcbz:
89 return AArch64MopT::MOP_wcbnz;
90 case AArch64MopT::MOP_wtbnz:
91 return AArch64MopT::MOP_wtbz;
92 case AArch64MopT::MOP_wtbz:
93 return AArch64MopT::MOP_wtbnz;
94 case AArch64MopT::MOP_xtbnz:
95 return AArch64MopT::MOP_xtbz;
96 case AArch64MopT::MOP_xtbz:
97 return AArch64MopT::MOP_xtbnz;
98 default:
99 break;
100 }
101 return AArch64MopT::MOP_undef;
102 }
103
GetJumpTargetIdx(const Insn & insn)104 uint32 GetJumpTargetIdx(const Insn &insn)
105 {
106 MOperator curMop = insn.GetMachineOpcode();
107 switch (curMop) {
108 /* unconditional jump */
109 case MOP_xuncond: {
110 return kInsnFirstOpnd;
111 }
112 case MOP_xbr: {
113 DEBUG_ASSERT(insn.GetOperandSize() == 2, "ERR"); // must have 2
114 return kInsnSecondOpnd;
115 }
116 /* conditional jump */
117 case MOP_bmi:
118 case MOP_bvc:
119 case MOP_bls:
120 case MOP_blt:
121 case MOP_ble:
122 case MOP_blo:
123 case MOP_beq:
124 case MOP_bpl:
125 case MOP_bhs:
126 case MOP_bvs:
127 case MOP_bhi:
128 case MOP_bgt:
129 case MOP_bge:
130 case MOP_bne:
131 case MOP_wcbz:
132 case MOP_xcbz:
133 case MOP_wcbnz:
134 case MOP_xcbnz: {
135 return kInsnSecondOpnd;
136 }
137 case MOP_wtbz:
138 case MOP_xtbz:
139 case MOP_wtbnz:
140 case MOP_xtbnz: {
141 return kInsnThirdOpnd;
142 }
143 default:
144 CHECK_FATAL(false, "Not a jump insn");
145 }
146 return kInsnFirstOpnd;
147 }
148
149 // This api is only used for cgir verify, implemented by calling the memopndofst interface.
GetMemOpndOffsetValue(Operand * o)150 int64 GetMemOpndOffsetValue(Operand *o)
151 {
152 auto *memOpnd = static_cast<MemOperand *>(o);
153 CHECK_FATAL(memOpnd != nullptr, "memOpnd should not be nullptr");
154 // kBOR memOpnd has no offsetvalue, so return 0 for verify.
155 // todo: AArch64AddressingMode is different from BiShengC
156 if (memOpnd->GetAddrMode() == MemOperand::kAddrModeBOrX) {
157 return 0;
158 }
159 // Offset value of kBOI & kLo12Li can be got.
160 OfstOperand *ofStOpnd = memOpnd->GetOffsetImmediate();
161 int64 offsetValue = ofStOpnd ? ofStOpnd->GetOffsetValue() : 0LL;
162 return offsetValue;
163 }
164
IsSub(const Insn & insn)165 bool IsSub(const Insn &insn)
166 {
167 MOperator curMop = insn.GetMachineOpcode();
168 switch (curMop) {
169 case MOP_xsubrrr:
170 case MOP_xsubrrrs:
171 case MOP_xsubrri24:
172 case MOP_xsubrri12:
173 case MOP_wsubrrr:
174 case MOP_wsubrrrs:
175 case MOP_wsubrri24:
176 case MOP_wsubrri12:
177 return true;
178 default:
179 return false;
180 }
181 }
182
GetMopSub2Subs(const Insn & insn)183 MOperator GetMopSub2Subs(const Insn &insn)
184 {
185 MOperator curMop = insn.GetMachineOpcode();
186 switch (curMop) {
187 case MOP_xsubrrr:
188 return MOP_xsubsrrr;
189 case MOP_xsubrrrs:
190 return MOP_xsubsrrrs;
191 case MOP_xsubrri24:
192 return MOP_xsubsrri24;
193 case MOP_xsubrri12:
194 return MOP_xsubsrri12;
195 case MOP_wsubrrr:
196 return MOP_wsubsrrr;
197 case MOP_wsubrrrs:
198 return MOP_wsubsrrrs;
199 case MOP_wsubrri24:
200 return MOP_wsubsrri24;
201 case MOP_wsubrri12:
202 return MOP_wsubsrri12;
203 default:
204 return curMop;
205 }
206 }
207
208 // Returns the number of trailing 0-bits in x, starting at the least significant bit position.
209 // If x is 0, the result is -1.
GetTail0BitNum(int64 val)210 int32 GetTail0BitNum(int64 val)
211 {
212 uint32 bitNum = 0;
213 for (; bitNum < k64BitSize; bitNum++) {
214 if (((1ULL << bitNum) & static_cast<uint64>(val)) != 0) {
215 break;
216 }
217 }
218 if (bitNum == k64BitSize) {
219 return -1;
220 }
221 return static_cast<int32>(bitNum);
222 }
223
224 // Returns the number of leading 0-bits in x, starting at the most significant bit position.
225 // If x is 0, the result is -1.
GetHead0BitNum(int64 val)226 int32 GetHead0BitNum(int64 val)
227 {
228 uint32 bitNum = 0;
229 for (; bitNum < k64BitSize; bitNum++) {
230 if (((0x8000000000000000ULL >> bitNum) & static_cast<uint64>(val)) != 0) {
231 break;
232 }
233 }
234 if (bitNum == k64BitSize) {
235 return -1;
236 }
237 return static_cast<int32>(bitNum);
238 }
239 } /* namespace AArch64isa */
240 } /* namespace maplebe */
241