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_utils.h"
17 #include "cg_option.h"
18
19 namespace maplebe {
20
GetOrCreateMemOperandForNewMOP(CGFunc & cgFunc,const Insn & loadIns,MOperator newLoadMop)21 MemOperand *GetOrCreateMemOperandForNewMOP(CGFunc &cgFunc, const Insn &loadIns, MOperator newLoadMop)
22 {
23 MemPool &memPool = *cgFunc.GetMemoryPool();
24 auto *memOp = static_cast<MemOperand *>(loadIns.GetMemOpnd());
25 MOperator loadMop = loadIns.GetMachineOpcode();
26
27 DEBUG_ASSERT(loadIns.IsLoad() && AArch64CG::kMd[newLoadMop].IsLoad(), "ins and Mop must be load");
28 DEBUG_ASSERT(memOp != nullptr, "memOp shoule not be nullptr");
29
30 MemOperand *newMemOp = memOp;
31
32 uint32 memSize = AArch64CG::kMd[loadMop].GetOperandSize();
33 uint32 newMemSize = AArch64CG::kMd[newLoadMop].GetOperandSize();
34 if (newMemSize == memSize) {
35 // if sizes are the same just return old memory operand
36 return newMemOp;
37 }
38
39 newMemOp = memOp->Clone(memPool);
40 newMemOp->SetSize(newMemSize);
41
42 if (!CGOptions::IsBigEndian()) {
43 return newMemOp;
44 }
45
46 // for big-endian it's necessary to adjust offset if it's present
47 if (memOp->GetAddrMode() != MemOperand::kAddrModeBOi || newMemSize > memSize) {
48 // currently, it's possible to adjust an offset only for immediate offset
49 // operand if new size is less than the original one
50 return nullptr;
51 }
52
53 auto *newOffOp = static_cast<OfstOperand *>(memOp->GetOffsetImmediate()->Clone(memPool));
54
55 newOffOp->AdjustOffset(static_cast<int32>((memSize - newMemSize) >> kLog2BitsPerByte));
56 newMemOp->SetOffsetOperand(*newOffOp);
57
58 DEBUG_ASSERT(memOp->IsOffsetMisaligned(memSize) || !newMemOp->IsOffsetMisaligned(newMemSize),
59 "New offset value is misaligned!");
60
61 return newMemOp;
62 }
63
64 } // namespace maplebe
65