1 /*
2 * Copyright (c) 2024 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 #ifndef MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_SPLIT_H
16 #define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_SPLIT_H
17
18 #include "aarch64_cg.h"
19 #include "aarch64_isa.h"
20 #include "cg_irbuilder.h"
21 #include "cgbb.h"
22 #include "common_utils.h"
23
24 namespace maplebe {
25 // Supply a new reg operand for insn split process, which type is kRegTyInt for immediate.
26 // Before regalloc: create a new virtual reg;
27 // After regalloc: use R16 to be a temporary physical reg.
GetSplitBaseReg(bool isAfterRegAlloc,bool is64Bits,OperandBuilder * opndBuilder)28 inline RegOperand *GetSplitBaseReg(bool isAfterRegAlloc, bool is64Bits, OperandBuilder *opndBuilder)
29 {
30 RegOperand *resOpnd = nullptr;
31 if (!isAfterRegAlloc) {
32 resOpnd = &opndBuilder->CreateVReg((is64Bits ? k64BitSize : k32BitSize), kRegTyInt);
33 } else {
34 resOpnd = &opndBuilder->CreatePReg(R16, (is64Bits ? k64BitSize : k32BitSize), kRegTyInt);
35 }
36 return resOpnd;
37 }
38
39 // Judging valid range of the immediate by passing in bitLen & forPair parameter, return the closest valid value to
40 // ofstVal, getting the remainder simultaneously. The valid value will be input in new memopnd, and the remainder
41 // will be input in add insn.
SplitGetRemained(const MemOperand & memOpnd,uint32 bitLen,int64 ofstVal,bool forPair,OperandBuilder * opndBuilder)42 inline ImmOperand &SplitGetRemained(const MemOperand &memOpnd, uint32 bitLen, int64 ofstVal, bool forPair,
43 OperandBuilder *opndBuilder)
44 {
45 // opndVal == Q0 * 32760(16380) + R0
46 // R0 == Q1 * 8(4) + R1
47 // ADDEND == Q0 * 32760(16380) + R1
48 // NEW_OFFSET = Q1 * 8(4)
49 // we want to generate two instructions:
50 // ADD TEMP_REG, X29, ADDEND
51 // LDR/STR TEMP_REG, [ TEMP_REG, #NEW_OFFSET ]
52 int32 maxPimm = 0;
53 if (!forPair) {
54 maxPimm = MemOperand::GetMaxPIMM(bitLen);
55 } else {
56 maxPimm = MemOperand::GetMaxPairPIMM(bitLen);
57 }
58 DEBUG_ASSERT(maxPimm != 0, "get max pimm failed");
59 int64 q0 = ofstVal / maxPimm + (ofstVal < 0 ? -1 : 0);
60 int64 addend = q0 * maxPimm;
61 uint64 r0 = static_cast<uint64>(ofstVal - addend);
62 uint64 alignment = static_cast<uint64>(static_cast<int64>(MemOperand::GetImmediateOffsetAlignment(bitLen)));
63 auto q1 = r0 >> alignment;
64 auto r1 = static_cast<int64>(r0 & ((1u << alignment) - 1));
65 auto remained = static_cast<int64>(q1 << alignment);
66 addend = addend + r1;
67 if (addend > 0) {
68 uint64 suffixClear = 0xfff;
69 if (forPair) {
70 suffixClear = 0xff;
71 }
72 int64 remainedTmp = remained + static_cast<int64>(static_cast<uint64>(addend) & suffixClear);
73 if (!MemOperand::IsPIMMOffsetOutOfRange(static_cast<int32>(remainedTmp), bitLen) &&
74 ((static_cast<uint64>(remainedTmp) & ((1u << alignment) - 1)) == 0)) {
75 addend = static_cast<int64>(static_cast<uint64>(addend) & ~suffixClear);
76 }
77 }
78 ImmOperand &immAddend = opndBuilder->CreateImm(k64BitSize, addend, true);
79 if (memOpnd.GetOffsetImmediate()->GetVary() == kUnAdjustVary) {
80 immAddend.SetVary(kUnAdjustVary);
81 }
82 return immAddend;
83 }
84
85 // Split Add Insn add reg, reg, #imm, steps as follows:
86 // If #imm value range 0 ~ 2^24 - 1, insn will be split into add reg, reg, #imm(, LSL 12)
87 // If #imm value out of range 2^24, insn will be split as follows:
88 // add x0, x1, #imm ====> mov x2, #imm
89 // add x0, x1, x2
AddInsnSplit(Insn * insn,bool is64Bits,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)90 inline void AddInsnSplit(Insn *insn, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
91 OperandBuilder *opndBuilder)
92 {
93 if (insn->VerifySelf()) {
94 return;
95 }
96 Operand *opnd0 = &insn->GetOperand(kInsnFirstOpnd);
97 Operand *opnd1 = &insn->GetOperand(kInsnSecondOpnd);
98 Operand *opnd2 = &insn->GetOperand(kInsnThirdOpnd);
99 ImmOperand *oldImmOpnd = static_cast<ImmOperand *>(opnd2);
100 ImmOperand *immOpnd =
101 &opndBuilder->CreateImm(oldImmOpnd->GetSize(), oldImmOpnd->GetValue(), oldImmOpnd->IsSignedValue());
102 immOpnd->SetVary(oldImmOpnd->GetVary());
103 insn->SetOperand(kInsnThirdOpnd, *immOpnd);
104 MOperator mOpCode = MOP_undef;
105 if (immOpnd->IsNegative()) {
106 immOpnd->Negate();
107 mOpCode = is64Bits ? MOP_xsubrri12 : MOP_wsubrri12;
108 insn->SetMOP(AArch64CG::kMd[mOpCode]);
109 if (!insn->VerifySelf()) {
110 insn->SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
111 }
112 return;
113 }
114 BB *bb = insn->GetBB();
115 // lower 24 bits has 1, higher bits are all 0
116 if (immOpnd->IsInBitSize(kMaxImmVal24Bits, 0)) {
117 // lower 12 bits and higher 12 bits both has 1
118 Operand *newOpnd1 = opnd1;
119 if (!(immOpnd->IsInBitSize(kMaxImmVal12Bits, 0) || immOpnd->IsInBitSize(kMaxImmVal12Bits, kMaxImmVal12Bits))) {
120 // process higher 12 bits
121 ImmOperand &immOpnd2 = opndBuilder->CreateImm(
122 immOpnd->GetSize(), static_cast<int64>(static_cast<uint64>(immOpnd->GetValue()) >> kMaxImmVal12Bits),
123 immOpnd->IsSignedValue());
124 mOpCode = is64Bits ? MOP_xaddrri24 : MOP_waddrri24;
125 RegOperand *tmpRes = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
126 BitShiftOperand &shiftopnd = opndBuilder->CreateBitShift(BitShiftOperand::kLSL, k12BitSize, k64BitSize);
127 Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *tmpRes, *opnd1, immOpnd2, shiftopnd);
128 newInsn.SetBB(bb);
129 DEBUG_ASSERT(newInsn.VerifySelf(), "immOpnd2 appears invalid");
130 (void)bb->InsertInsnBefore(*insn, newInsn);
131 // get lower 12 bits value
132 immOpnd->ModuloByPow2(kMaxImmVal12Bits);
133 newOpnd1 = tmpRes;
134 }
135 // process lower 12 bits value
136 mOpCode = is64Bits ? MOP_xaddrri12 : MOP_waddrri12;
137 // It`s worth noting that if immOpnd->IsInBitSize(12, 12) returns true, gcc assembler can compile correctly,
138 // so we pass immOpnd directly as a parameter.
139 Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *newOpnd1, *immOpnd);
140 newInsn.SetBB(bb);
141 DEBUG_ASSERT(newInsn.VerifySelf(), "immOpnd appears invalid");
142 bb->ReplaceInsn(*insn, newInsn);
143 return;
144 } else {
145 // load into register
146 int64 immVal = immOpnd->GetValue();
147 int32 tail0bitNum = AArch64isa::GetTail0BitNum(immVal);
148 int32 head0bitNum = AArch64isa::GetHead0BitNum(immVal);
149 const int32 bitNum = (k64BitSizeInt - head0bitNum) - tail0bitNum;
150 RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
151 regno_t regNO0 = static_cast<RegOperand *>(opnd1)->GetRegisterNumber();
152 // The content of the next if code block is when immvalue can be moved in one insn, we do next:
153 // add x0, x1, #imm1 ====> mov x2, #imm2
154 // add x0, x1, x2, LSL <shift>
155 // #imm2 = #imm1 >> shift
156 // addrrrs do not support sp
157 if (bitNum <= k16BitSizeInt && regNO0 != RSP) {
158 int64 newImm =
159 static_cast<int64>((static_cast<uint64>(immVal) >> static_cast<uint32>(tail0bitNum)) & 0xFFFF);
160 ImmOperand &immOpnd1 = opndBuilder->CreateImm(k16BitSize, newImm, false);
161 mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
162 Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, immOpnd1);
163 movInsn.SetBB(bb);
164 (void)bb->InsertInsnBefore(*insn, movInsn);
165 mOpCode = is64Bits ? MOP_xaddrrrs : MOP_waddrrrs;
166 // bitLen means bitshiftopnd size: 64bits -> 6, 32bits ->5
167 uint32 bitLen = is64Bits ? k6BitSize : k5BitSize;
168 BitShiftOperand &bitShiftOpnd =
169 opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast<uint32>(tail0bitNum), bitLen);
170 Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd, bitShiftOpnd);
171 newInsn.SetBB(bb);
172 bb->ReplaceInsn(*insn, newInsn);
173 return;
174 }
175 mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
176 Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, *immOpnd);
177 movInsn.SetBB(bb);
178 mOpCode = is64Bits ? MOP_xaddrrr : MOP_waddrrr;
179 Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd);
180 newInsn.SetBB(bb);
181 (void)bb->InsertInsnBefore(*insn, movInsn);
182 // If #imm of mov is invalid, split mov insn
183 if (!movInsn.VerifySelf()) {
184 movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
185 }
186 bb->ReplaceInsn(*insn, newInsn);
187 }
188 }
189
190 // Split Sub Insn sub reg, reg, #imm, the same split steps as add
SubInsnSplit(Insn * insn,bool is64Bits,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)191 inline void SubInsnSplit(Insn *insn, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
192 OperandBuilder *opndBuilder)
193 {
194 if (insn->VerifySelf()) {
195 return;
196 }
197 Operand *opnd0 = &insn->GetOperand(kInsnFirstOpnd);
198 Operand *opnd1 = &insn->GetOperand(kInsnSecondOpnd);
199 Operand *opnd2 = &insn->GetOperand(kInsnThirdOpnd);
200 ImmOperand *oldImmOpnd = static_cast<ImmOperand *>(opnd2);
201 ImmOperand *immOpnd =
202 &opndBuilder->CreateImm(oldImmOpnd->GetSize(), oldImmOpnd->GetValue(), oldImmOpnd->IsSignedValue());
203 immOpnd->SetVary(oldImmOpnd->GetVary());
204 insn->SetOperand(kInsnThirdOpnd, *immOpnd);
205 MOperator mOpCode = MOP_undef;
206 if (immOpnd->IsNegative()) {
207 immOpnd->Negate();
208 mOpCode = is64Bits ? MOP_xaddrri12 : MOP_waddrri12;
209 insn->SetMOP(AArch64CG::kMd[mOpCode]);
210 if (!insn->VerifySelf()) {
211 insn->SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
212 }
213 return;
214 }
215 BB *bb = insn->GetBB();
216 int64 higher12BitVal = static_cast<int64>(static_cast<uint64>(immOpnd->GetValue()) >> kMaxImmVal12Bits);
217 if (immOpnd->IsInBitSize(kMaxImmVal24Bits, 0) && higher12BitVal + 1 <= kMaxPimm8) {
218 // SUB Wd|WSP, Wn|WSP, #imm{, shift} ; 32-bit general registers
219 // SUB Xd|SP, Xn|SP, #imm{, shift} ; 64-bit general registers
220 // imm : 0 ~ 4095, shift: none, LSL #0, or LSL #12
221 // aarch64 assembly takes up to 24-bits, if the lower 12 bits is all 0
222 // large offset is treated as sub (higher 12 bits + 4096) + add
223 // it gives opportunities for combining add + ldr due to the characteristics of aarch64's load/store
224 bool isSplitSub = false;
225 Operand *newOpnd1 = opnd1;
226 if (!(immOpnd->IsInBitSize(kMaxImmVal12Bits, 0) || immOpnd->IsInBitSize(kMaxImmVal12Bits, kMaxImmVal12Bits))) {
227 isSplitSub = true;
228 // process higher 12 bits
229 ImmOperand &immOpnd2 =
230 opndBuilder->CreateImm(immOpnd->GetSize(), higher12BitVal + 1, immOpnd->IsSignedValue());
231 mOpCode = is64Bits ? MOP_xsubrri24 : MOP_wsubrri24;
232 RegOperand *resOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
233 BitShiftOperand &shiftopnd = opndBuilder->CreateBitShift(BitShiftOperand::kLSL, k12BitSize, k64BitSize);
234 Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *resOpnd, *opnd1, immOpnd2, shiftopnd);
235 newInsn.SetBB(bb);
236 (void)bb->InsertInsnBefore(*insn, newInsn);
237 immOpnd->ModuloByPow2(kMaxImmVal12Bits);
238 immOpnd->SetValue(static_cast<int64>(kMax12UnsignedImm) - immOpnd->GetValue());
239 newOpnd1 = resOpnd;
240 }
241 // process lower 12 bits
242 mOpCode = isSplitSub ? (is64Bits ? MOP_xaddrri12 : MOP_waddrri12) : (is64Bits ? MOP_xsubrri12 : MOP_wsubrri12);
243 Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *newOpnd1, *immOpnd);
244 newInsn.SetBB(bb);
245 bb->ReplaceInsn(*insn, newInsn);
246 return;
247 } else {
248 // load into register
249 int64 immVal = immOpnd->GetValue();
250 int32 tail0bitNum = AArch64isa::GetTail0BitNum(immVal);
251 int32 head0bitNum = AArch64isa::GetHead0BitNum(immVal);
252 const int32 bitNum = (k64BitSizeInt - head0bitNum) - tail0bitNum;
253 RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
254 // The content of the next if code block is when immvalue can be moved in one insn, we do next:
255 // sub x0, x1, #imm1 ====> mov x2, #imm2
256 // sub x0, x1, x2, LSL <shift>
257 // #imm2 = #imm1 >> shift
258 // subrrrs supports sp, so do not need to check whether regNo is RSP
259 if (bitNum <= k16BitSizeInt) {
260 int64 newImm =
261 static_cast<int64>((static_cast<uint64>(immVal) >> static_cast<uint32>(tail0bitNum)) & 0xFFFF);
262 ImmOperand &immOpnd1 = opndBuilder->CreateImm(k16BitSize, newImm, false);
263 mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
264 Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, immOpnd1);
265 movInsn.SetBB(bb);
266 (void)bb->InsertInsnBefore(*insn, movInsn);
267 mOpCode = is64Bits ? MOP_xsubrrrs : MOP_wsubrrrs;
268 // bitLen means bitshiftopnd size: 64bits -> 6, 32bits ->5
269 uint32 bitLen = is64Bits ? k6BitSize : k5BitSize;
270 BitShiftOperand &bitShiftOpnd =
271 opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast<uint32>(tail0bitNum), bitLen);
272 Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd, bitShiftOpnd);
273 newInsn.SetBB(bb);
274 bb->ReplaceInsn(*insn, newInsn);
275 return;
276 }
277 mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
278 Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, *immOpnd);
279 movInsn.SetBB(bb);
280 mOpCode = is64Bits ? MOP_xsubrrr : MOP_wsubrrr;
281 Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd);
282 newInsn.SetBB(bb);
283 (void)bb->InsertInsnBefore(*insn, movInsn);
284 // If #imm of mov is invalid, split mov insn
285 if (!movInsn.VerifySelf()) {
286 movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
287 }
288 bb->ReplaceInsn(*insn, newInsn);
289 }
290 }
291
292 // adds & subs updates the condition flags based on the result, so it cannot be split into multiple instructions
293 // of the same type, because we don`t know when the result is out of range and changes flags. The solution is:
294 // adds/subs x0, x1, #imm ====> mov x2, #imm
295 // adds/subs x0, x1, x2
296 // isAdds: true -> adds, false -> subs
AddsSubsInsnSplit(Insn * insn,bool isAdds,bool is64Bits,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)297 inline void AddsSubsInsnSplit(Insn *insn, bool isAdds, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
298 OperandBuilder *opndBuilder)
299 {
300 if (insn->VerifySelf()) {
301 return;
302 }
303 Operand *opnd0 = &insn->GetOperand(kInsnFirstOpnd);
304 Operand *opnd1 = &insn->GetOperand(kInsnSecondOpnd);
305 Operand *opnd2 = &insn->GetOperand(kInsnThirdOpnd);
306 Operand *opnd3 = &insn->GetOperand(kInsnFourthOpnd);
307 ImmOperand *immOpnd = static_cast<ImmOperand *>(opnd3);
308 MOperator mOpCode = MOP_undef;
309 BB *bb = insn->GetBB();
310 RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
311 mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
312 Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, *immOpnd);
313 movInsn.SetBB(bb);
314 mOpCode = isAdds ? (is64Bits ? MOP_xaddsrrr : MOP_waddsrrr) : (is64Bits ? MOP_xsubsrrr : MOP_wsubsrrr);
315 Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *opnd2, *movOpnd);
316 newInsn.SetBB(bb);
317 (void)bb->InsertInsnBefore(*insn, movInsn);
318 // If #imm of mov is invalid, split mov first.
319 if (!movInsn.VerifySelf()) {
320 movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
321 }
322 (void)bb->InsertInsnBefore(*insn, newInsn);
323 bb->RemoveInsn(*insn);
324 }
325
326 // Split Add/Sub Insn with BitShiftOperand (LSL 12), steps as follows:
327 // add/sub x0, x1, #imm, LSL 12 ====> add/sub x0, x1, #newimm ====> Add/SubInsnSplit
328 // isAdd: true -> add, false -> sub
AddSubWithLslSplit(Insn * insn,bool isAdd,bool is64Bits,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)329 inline void AddSubWithLslSplit(Insn *insn, bool isAdd, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
330 OperandBuilder *opndBuilder)
331 {
332 if (insn->VerifySelf()) {
333 return;
334 }
335 uint32 size = is64Bits ? k64BitSize : k32BitSize;
336 ImmOperand &immOpnd = static_cast<ImmOperand &>(insn->GetOperand(kInsnThirdOpnd));
337 // add/sub x0, x1, #imm, LSL 12 ====> imm value range can be split: 2^12 ~ 2^52 - 1
338 // add/sub w0, w1, #imm, LSL 12 ====> imm value range can be split: 2^12 ~ 2^20 - 1
339 // If imm is out of range, insn will not be split
340 if (!immOpnd.IsInBitSize((size - k12BitSize), k0BitSize)) {
341 return;
342 }
343 BB *bb = insn->GetBB();
344 ImmOperand &newImmOpnd =
345 opndBuilder->CreateImm(size, static_cast<int64>(static_cast<uint64>(immOpnd.GetValue()) << k12BitSize));
346 MOperator mOpCode = is64Bits ? (isAdd ? MOP_xaddrri12 : MOP_xsubrri12) : (isAdd ? MOP_waddrri12 : MOP_wsubrri12);
347 Insn &newInsn = insnBuilder->BuildInsn(mOpCode, insn->GetOperand(kInsnFirstOpnd), insn->GetOperand(kInsnSecondOpnd),
348 newImmOpnd);
349 newInsn.SetBB(bb);
350 bb->ReplaceInsn(*insn, newInsn);
351 if (!newInsn.VerifySelf()) {
352 newInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
353 }
354 }
355
356 // Split memoperand with invalid offset value to a new valid memoperand and add insn with remainder.
MemOfstSplitWithAdd(const MemOperand & memOpnd,uint32 bitLen,bool isAfterRegAlloc,Insn * insn,bool forPair,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)357 inline MemOperand &MemOfstSplitWithAdd(const MemOperand &memOpnd, uint32 bitLen, bool isAfterRegAlloc, Insn *insn,
358 bool forPair, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
359 {
360 DEBUG_ASSERT((memOpnd.GetAddrMode() == MemOperand::kAddrModeBOi), "expect kAddrModeBOi memOpnd");
361 DEBUG_ASSERT(memOpnd.IsIntactIndexed(), "expect intactIndexed memOpnd");
362 BB *bb = insn->GetBB();
363 OfstOperand *ofstOpnd = memOpnd.GetOffsetImmediate();
364 int64 ofstVal = ofstOpnd->GetOffsetValue();
365 RegOperand *resOpnd = GetSplitBaseReg(isAfterRegAlloc, true, opndBuilder);
366 ImmOperand &immAddend = SplitGetRemained(memOpnd, bitLen, ofstVal, forPair, opndBuilder);
367 int64 remained = (ofstVal - immAddend.GetValue());
368 RegOperand *origBaseReg = memOpnd.GetBaseRegister();
369 DEBUG_ASSERT(origBaseReg != nullptr, "nullptr check");
370 // Provide add insn to split offset, where add insn is 64-bit explicitly
371 Insn &addInsn = insnBuilder->BuildInsn(MOP_xaddrri12, *resOpnd, *origBaseReg, immAddend);
372 addInsn.SetBB(bb);
373 bb->InsertInsnBefore(*insn, addInsn);
374 if (!addInsn.VerifySelf()) {
375 addInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
376 }
377 ImmOperand &remainedOpnd = opndBuilder->CreateImm(k32BitSize, remained, true);
378 MemOperand &newMemOpnd = opndBuilder->CreateMem(bitLen, *resOpnd, remainedOpnd);
379 newMemOpnd.SetStackMem(memOpnd.IsStackMem());
380 return newMemOpnd;
381 }
382
383 // Split a load/store insn with invalid offset value to a new valid insn and add insn.
384 // idx: memOperand index of insn
LoadStoreInsnSplit(Insn * insn,uint32 idx,bool forPair,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)385 inline void LoadStoreInsnSplit(Insn *insn, uint32 idx, bool forPair, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
386 OperandBuilder *opndBuilder)
387 {
388 if (insn->VerifySelf()) {
389 return;
390 }
391 MemOperand &memOpnd = static_cast<MemOperand &>(insn->GetOperand(idx));
392 if (!(memOpnd.GetAddrMode() == MemOperand::kAddrModeBOi && memOpnd.IsIntactIndexed())) {
393 return;
394 }
395 uint32 bitLen = insn->GetDesc()->GetOpndDes(idx)->GetSize();
396 MemOperand &newMemOpnd =
397 MemOfstSplitWithAdd(memOpnd, bitLen, isAfterRegAlloc, insn, forPair, insnBuilder, opndBuilder);
398 insn->SetOperand(idx, newMemOpnd);
399 }
400
401 // ccmp updates the condition flags based on the result, so it cannot be split into multiple instructions
402 // of the same type, because we don`t know when the result is out of range and changes flags. The solution is:
403 // ccmp <Xn>, #<imm>, #<nzcv>, <cond> ====> mov <Xm>, #<imm>
404 // ccmp <Xn>, <Xm>, #<nzcv>, <cond>
CondCompareInsnSplit(Insn * insn,bool is64Bits,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)405 inline void CondCompareInsnSplit(Insn *insn, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
406 OperandBuilder *opndBuilder)
407 {
408 if (insn->VerifySelf()) {
409 return;
410 }
411 ImmOperand &immOpnd = static_cast<ImmOperand &>(insn->GetOperand(kInsnSecondOpnd));
412 MOperator mOpCode = MOP_undef;
413 BB *bb = insn->GetBB();
414 RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder);
415 mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32;
416 Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, immOpnd);
417 movInsn.SetBB(bb);
418 bb->InsertInsnBefore(*insn, movInsn);
419 if (!movInsn.VerifySelf()) {
420 movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder);
421 }
422 mOpCode = is64Bits ? MOP_xccmprric : MOP_wccmprric;
423 insn->SetMOP(AArch64CG::kMd[mOpCode]);
424 insn->SetOperand(kInsnSecondOpnd, *movOpnd);
425 }
426
427 // split mov w0, #imm to mov and movk
MOP_wmovri32Split(Insn * curInsn,bool,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)428 inline void MOP_wmovri32Split(Insn *curInsn, bool /* isAfterRegAlloc */, InsnBuilder *insnBuilder,
429 OperandBuilder *opndBuilder)
430 {
431 // If higher 32bits of immVal have 1, we will truncate and keep lower 32 bits.
432 int64 immVal = static_cast<int64>(
433 static_cast<uint64>(static_cast<ImmOperand &>(curInsn->GetOperand(kInsnSecondOpnd)).GetValue()) &
434 0x00000000FFFFFFFFULL);
435 ImmOperand &immOpnd = opndBuilder->CreateImm(k64BitSize, immVal, true);
436 curInsn->SetOperand(kInsnSecondOpnd, immOpnd);
437 if (curInsn->VerifySelf()) {
438 return;
439 }
440 RegOperand &destReg = static_cast<RegOperand &>(curInsn->GetOperand(kInsnFirstOpnd));
441 auto *bb = curInsn->GetBB();
442 uint64 chunkVal0 = static_cast<uint64>(immVal) & 0x0000FFFFULL;
443 ImmOperand &src0 = opndBuilder->CreateImm(k16BitSize, static_cast<int64>(chunkVal0), false);
444 Insn &movInsn = insnBuilder->BuildInsn(MOP_wmovri32, destReg, src0);
445 movInsn.SetBB(bb);
446 (void)bb->InsertInsnBefore(*curInsn, movInsn);
447 uint64 chunkVal1 = (static_cast<uint64>(immVal) >> k16BitSize) & 0x0000FFFFULL;
448 ImmOperand &src16 = opndBuilder->CreateImm(k16BitSize, static_cast<int64>(chunkVal1), false);
449 BitShiftOperand *lslOpnd = &opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast<uint32>(k16BitSize), 6);
450 Insn &movkInsn = insnBuilder->BuildInsn(MOP_wmovkri16, destReg, src16, *lslOpnd);
451 movkInsn.SetBB(bb);
452 (void)bb->InsertInsnBefore(*curInsn, movkInsn);
453 bb->RemoveInsn(*curInsn);
454 }
455
456 // split mov x0, #imm to movz/movn and movk
MOP_xmovri64Split(Insn * curInsn,bool,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)457 inline void MOP_xmovri64Split(Insn *curInsn, bool /* isAfterRegAlloc */, InsnBuilder *insnBuilder,
458 OperandBuilder *opndBuilder)
459 {
460 if (curInsn->VerifySelf()) {
461 return;
462 }
463 RegOperand &destReg = static_cast<RegOperand &>(curInsn->GetOperand(kInsnFirstOpnd));
464 int64 immVal = static_cast<ImmOperand &>(curInsn->GetOperand(kInsnSecondOpnd)).GetValue();
465 bool useMovz = BetterUseMOVZ(static_cast<uint64>(immVal));
466 bool useMovk = false;
467 // get lower 32 bits of the immediate
468 uint64 chunkLval = static_cast<uint64>(immVal) & 0xFFFFFFFFULL;
469 // get upper 32 bits of the immediate
470 uint64 chunkHval = (static_cast<uint64>(immVal) >> k32BitSize) & 0xFFFFFFFFULL;
471 int32 maxLoopTime = 4;
472 if (chunkLval == chunkHval) {
473 // compute lower 32 bits, and then copy to higher 32 bits, so only 2 chunks need be processed
474 maxLoopTime = 2;
475 }
476 uint64 sa = 0;
477 auto *bb = curInsn->GetBB();
478 for (int64 i = 0; i < maxLoopTime; ++i, sa += k16BitSize) {
479 // create an imm opereand which represents the i-th 16-bit chunk of the immediate
480 uint64 chunkVal = (static_cast<uint64>(immVal) >> sa) & 0x0000FFFFULL;
481 if (useMovz ? (chunkVal == 0) : (chunkVal == 0x0000FFFFULL)) {
482 continue;
483 }
484 ImmOperand &src16 = opndBuilder->CreateImm(k16BitSize, static_cast<int64>(chunkVal), false);
485 BitShiftOperand *lslOpnd = &opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast<uint32>(sa), 6);
486 Insn *newInsn = nullptr;
487 if (!useMovk) {
488 // use movz or movn
489 if (!useMovz) {
490 src16.BitwiseNegate();
491 }
492 MOperator mOpCode = useMovz ? MOP_xmovzri16 : MOP_xmovnri16;
493 newInsn = &insnBuilder->BuildInsn(mOpCode, destReg, src16, *lslOpnd);
494 newInsn->SetBB(bb);
495 useMovk = true;
496 } else {
497 newInsn = &insnBuilder->BuildInsn(MOP_xmovkri16, destReg, src16, *lslOpnd);
498 newInsn->SetBB(bb);
499 }
500 (void)bb->InsertInsnBefore(*curInsn, *newInsn);
501 }
502 constexpr int32 loopTime = 2;
503 if (maxLoopTime == loopTime) {
504 // copy lower 32 bits to higher 32 bits
505 ImmOperand &immOpnd = opndBuilder->CreateImm(k8BitSize, k32BitSize, false);
506 Insn &insn = insnBuilder->BuildInsn(MOP_xbfirri6i6, destReg, destReg, immOpnd, immOpnd);
507 insn.SetBB(bb);
508 (void)bb->InsertInsnBefore(*curInsn, insn);
509 }
510 bb->RemoveInsn(*curInsn);
511 }
512
MOP_xaddrri24Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)513 inline void MOP_xaddrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
514 {
515 AddSubWithLslSplit(insn, true, true, isAfterRegAlloc, insnBuilder, opndBuilder);
516 }
517
MOP_xaddrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)518 inline void MOP_xaddrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
519 {
520 AddInsnSplit(insn, true, isAfterRegAlloc, insnBuilder, opndBuilder);
521 }
522
MOP_xaddsrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)523 inline void MOP_xaddsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
524 {
525 AddsSubsInsnSplit(insn, true, true, isAfterRegAlloc, insnBuilder, opndBuilder);
526 }
527
MOP_waddrri24Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)528 inline void MOP_waddrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
529 {
530 AddSubWithLslSplit(insn, true, false, isAfterRegAlloc, insnBuilder, opndBuilder);
531 }
532
MOP_waddrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)533 inline void MOP_waddrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
534 {
535 AddInsnSplit(insn, false, isAfterRegAlloc, insnBuilder, opndBuilder);
536 }
537
MOP_waddsrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)538 inline void MOP_waddsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
539 {
540 AddsSubsInsnSplit(insn, true, false, isAfterRegAlloc, insnBuilder, opndBuilder);
541 }
542
MOP_xsubrri24Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)543 inline void MOP_xsubrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
544 {
545 AddSubWithLslSplit(insn, false, true, isAfterRegAlloc, insnBuilder, opndBuilder);
546 }
547
MOP_xsubrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)548 inline void MOP_xsubrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
549 {
550 SubInsnSplit(insn, true, isAfterRegAlloc, insnBuilder, opndBuilder);
551 }
552
MOP_xsubsrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)553 inline void MOP_xsubsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
554 {
555 AddsSubsInsnSplit(insn, false, true, isAfterRegAlloc, insnBuilder, opndBuilder);
556 }
557
MOP_wsubrri24Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)558 inline void MOP_wsubrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
559 {
560 AddSubWithLslSplit(insn, false, false, isAfterRegAlloc, insnBuilder, opndBuilder);
561 }
562
MOP_wsubrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)563 inline void MOP_wsubrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
564 {
565 SubInsnSplit(insn, false, isAfterRegAlloc, insnBuilder, opndBuilder);
566 }
567
MOP_wsubsrri12Split(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)568 inline void MOP_wsubsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
569 {
570 AddsSubsInsnSplit(insn, false, false, isAfterRegAlloc, insnBuilder, opndBuilder);
571 }
572
MOP_wldrsbSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)573 inline void MOP_wldrsbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
574 {
575 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
576 }
577
MOP_xldrsbSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)578 inline void MOP_xldrsbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
579 {
580 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
581 }
582
MOP_wldrbSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)583 inline void MOP_wldrbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
584 {
585 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
586 }
587
MOP_wldrshSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)588 inline void MOP_wldrshSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
589 {
590 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
591 }
592
MOP_xldrshSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)593 inline void MOP_xldrshSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
594 {
595 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
596 }
597
MOP_xldrswSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)598 inline void MOP_xldrswSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
599 {
600 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
601 }
602
MOP_wldrhSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)603 inline void MOP_wldrhSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
604 {
605 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
606 }
607
MOP_wldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)608 inline void MOP_wldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
609 {
610 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
611 }
612
MOP_xldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)613 inline void MOP_xldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
614 {
615 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
616 }
617
MOP_bldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)618 inline void MOP_bldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
619 {
620 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
621 }
622
MOP_hldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)623 inline void MOP_hldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
624 {
625 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
626 }
627
MOP_sldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)628 inline void MOP_sldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
629 {
630 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
631 }
632
MOP_dldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)633 inline void MOP_dldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
634 {
635 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
636 }
637
MOP_qldrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)638 inline void MOP_qldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
639 {
640 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
641 }
642
MOP_wldpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)643 inline void MOP_wldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
644 {
645 LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
646 }
647
MOP_xldpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)648 inline void MOP_xldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
649 {
650 LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
651 }
652
MOP_xldpswSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)653 inline void MOP_xldpswSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
654 {
655 LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
656 }
657
MOP_sldpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)658 inline void MOP_sldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
659 {
660 LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
661 }
662
MOP_dldpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)663 inline void MOP_dldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
664 {
665 LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
666 }
667
MOP_qldpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)668 inline void MOP_qldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
669 {
670 LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
671 }
672
MOP_wccmpriicSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)673 inline void MOP_wccmpriicSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
674 {
675 CondCompareInsnSplit(insn, false, isAfterRegAlloc, insnBuilder, opndBuilder);
676 }
677
MOP_xccmpriicSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)678 inline void MOP_xccmpriicSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
679 {
680 CondCompareInsnSplit(insn, true, isAfterRegAlloc, insnBuilder, opndBuilder);
681 }
682
MOP_wstrbSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)683 inline void MOP_wstrbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
684 {
685 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
686 }
687
MOP_wstrhSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)688 inline void MOP_wstrhSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
689 {
690 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
691 }
692
MOP_wstrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)693 inline void MOP_wstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
694 {
695 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
696 }
697
MOP_xstrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)698 inline void MOP_xstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
699 {
700 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
701 }
702
MOP_sstrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)703 inline void MOP_sstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
704 {
705 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
706 }
707
MOP_dstrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)708 inline void MOP_dstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
709 {
710 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
711 }
712
MOP_qstrSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)713 inline void MOP_qstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
714 {
715 LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder);
716 }
717
MOP_wstpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)718 inline void MOP_wstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
719 {
720 LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
721 }
722
MOP_xstpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)723 inline void MOP_xstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
724 {
725 LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
726 }
727
MOP_sstpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)728 inline void MOP_sstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
729 {
730 LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
731 }
732
MOP_dstpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)733 inline void MOP_dstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
734 {
735 LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
736 }
737
MOP_qstpSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)738 inline void MOP_qstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
739 {
740 LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder);
741 }
742
MOP_assert_nonnullSplit(Insn * insn,bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)743 inline void MOP_assert_nonnullSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder,
744 OperandBuilder *opndBuilder)
745 {
746 MOP_wldrSplit(insn, isAfterRegAlloc, insnBuilder, opndBuilder);
747 }
748 } /* namespace maplebe */
749 #endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_SPLIT_H */
750