diff --git a/ecmascript/compiler/codegen/maple/maple_be/BUILD.gn b/ecmascript/compiler/codegen/maple/maple_be/BUILD.gn index 94b529d9165de70cdf9244b1e8e6d02b45349a1e..2527d7b885fb50cdebaf0813ebf335f073988f84 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/BUILD.gn +++ b/ecmascript/compiler/codegen/maple/maple_be/BUILD.gn @@ -101,6 +101,7 @@ src_libcgaarch64 = [ "src/cg/aarch64/aarch64_abi.cpp", "src/cg/aarch64/aarch64_call_conv.cpp", "src/cg/aarch64/mpl_atomic.cpp", + "src/cg/aarch64/aarch64_cfi_generator.cpp", "src/cg/aarch64/aarch64_cgfunc.cpp", "src/cg/aarch64/aarch64_dependence.cpp", "src/cg/aarch64/aarch64_ebo.cpp", @@ -137,6 +138,7 @@ src_libcgaarch64 = [ "src/cg/aarch64/aarch64_cg.cpp", "src/cg/aarch64/aarch64_validbit_opt.cpp", "src/cg/aarch64/aarch64_cfgo.cpp", + "src/cg/aarch64/aarch64_imm_valid.cpp", ] src_libcgx86phases = [ @@ -206,6 +208,7 @@ src_libcgriscv64 = [ src_libcgark = [ "src/cg/ark/foo.cpp" ] src_libcgphases = [ + "src/cg/cfi_generator.cpp", "src/cg/cfgo.cpp", "src/cg/local_opt.cpp", "src/cg/ebo.cpp", diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/ad/mad.h b/ecmascript/compiler/codegen/maple/maple_be/include/ad/mad.h index aca332d2b862356167878838c1cda0ef83740925..28585b1cd09c70fcbd1270f331d3cc5a126f61e4 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/ad/mad.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/ad/mad.h @@ -16,11 +16,13 @@ #ifndef MAPLEBE_INCLUDE_AD_MAD_H #define MAPLEBE_INCLUDE_AD_MAD_H #include +#include #include "types_def.h" #include "mpl_logging.h" #include "insn.h" namespace maplebe { +constexpr int kOccupyWidth = 32; enum UnitId : maple::uint32 { #include "mplad_unit_id.def" kUnitIdLast @@ -68,16 +70,16 @@ public: const std::vector &GetCompositeUnits() const; std::string GetName() const; - bool IsFree(maple::uint32 cycle) const; - void Occupy(const Insn &insn, maple::uint32 cycle); + bool IsIdle(uint32 cycle) const; + void Occupy(uint32 cycle); void Release(); - void AdvanceCycle(); + void AdvanceOneCycle(); void Dump(int indent = 0) const; - maple::uint32 GetOccupancyTable() const; + std::bitset GetOccupancyTable() const; - void SetOccupancyTable(maple::uint32 table) + void SetOccupancyTable(const std::bitset value) { - occupancyTable = table; + occupancyTable = value; } private: @@ -85,7 +87,8 @@ private: enum UnitId unitId; enum UnitType unitType; - maple::uint32 occupancyTable; + // using 32-bit vector simulating resource occupation, the LSB always indicates the current cycle by AdvanceOneCycle + std::bitset occupancyTable; std::vector compositeUnits; }; @@ -178,15 +181,14 @@ public: void InitParallelism() const; void InitReservation() const; void InitBypass() const; - bool IsSlot0Free() const; bool IsFullIssued() const; int GetLatency(const Insn &def, const Insn &use) const; int DefaultLatency(const Insn &insn) const; Reservation *FindReservation(const Insn &insn) const; - void AdvanceCycle() const; + void AdvanceOneCycleForAll() const; void ReleaseAllUnits() const; - void SaveStates(std::vector &occupyTable, int size) const; - void RestoreStates(std::vector &occupyTable, int size) const; + void SaveStates(std::vector> &occupyTable, int size) const; + void RestoreStates(std::vector> &occupyTable, int size) const; int GetMaxParallelism() const { @@ -252,10 +254,10 @@ public: bool CanBypass(const Insn &defInsn, const Insn &useInsn) const override; }; -class StoreBypass : public Bypass { +class StoreAddrBypass : public Bypass { public: - StoreBypass(LatencyType d, LatencyType u, int l) : Bypass(d, u, l) {} - ~StoreBypass() override = default; + StoreAddrBypass(LatencyType d, LatencyType u, int l) : Bypass(d, u, l) {} + ~StoreAddrBypass() override = default; bool CanBypass(const Insn &defInsn, const Insn &useInsn) const override; }; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/be/common_utils.h b/ecmascript/compiler/codegen/maple/maple_be/include/be/common_utils.h index 75f424baa893ea6f54e104d73160d04dbe16a5c7..3bbce343be926b206553e34b3854fc767a5b1636 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/be/common_utils.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/be/common_utils.h @@ -42,6 +42,7 @@ constexpr uint32 k6BitSize = 6; constexpr uint32 k7BitSize = 7; constexpr uint32 k8BitSize = 8; constexpr uint32 k12BitSize = 12; +constexpr uint32 k15BitSize = 15; constexpr uint32 k16BitSize = 16; constexpr uint32 k24BitSize = 24; constexpr uint32 k32BitSize = 32; @@ -81,6 +82,7 @@ constexpr int32 kNegative256BitSize = -256; constexpr int32 kNegative512BitSize = -512; constexpr int32 kNegative1024BitSize = -1024; +constexpr uint32 k0ByteSize = 0; constexpr uint32 k1ByteSize = 1; constexpr uint32 k2ByteSize = 2; constexpr uint32 k3ByteSize = 3; @@ -209,6 +211,7 @@ constexpr int32 kMinSimm32 = kNegative256BitSize; constexpr int32 kMaxSimm64Pair = 504; constexpr int32 kMinSimm64 = kNegative512BitSize; +constexpr int32 kMax8UnsignedImm = 255; constexpr int32 kMax12UnsignedImm = 4096; constexpr int32 kMax13UnsignedImm = 8192; constexpr int32 kMax16UnsignedImm = 65535; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/be/lower.h b/ecmascript/compiler/codegen/maple/maple_be/include/be/lower.h index 864c64b0ac3e7de6082b8ba08a427d231321ec4c..9cb3831bcfba3fab32d4e9b8993cc46627751204 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/be/lower.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/be/lower.h @@ -169,10 +169,15 @@ public: BaseNode *LowerCArray(ArrayNode &array); DassignNode *SaveReturnValueInLocal(StIdx, uint16); + BaseNode *NeedRetypeWhenLowerCallAssigned(PrimType pType); void LowerCallStmt(StmtNode &, StmtNode *&, BlockNode &, MIRType *retty = nullptr, bool uselvar = false, bool isIntrinAssign = false); BlockNode *LowerIntrinsiccallAassignedToAssignStmt(IntrinsiccallNode &intrinsicCall); BlockNode *LowerCallAssignedStmt(StmtNode &stmt, bool uselvar = false); + /* Intrinsiccall will processe return and vector as a call separately. + * To be able to handle them in a unified manner, we lower intrinsiccall to Intrinsicsicop. + */ + BlockNode *LowerIntrinsiccallToIntrinsicop(StmtNode &stmt); bool LowerStructReturn(BlockNode &blk, StmtNode *stmt, StmtNode *&nextStmt, bool &lvar, BlockNode *oldblk); BlockNode *LowerMemop(StmtNode &); diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cfi_generator.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cfi_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..f52a0f169f1e580fd04bfaeb2bfc06dae7807c89 --- /dev/null +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cfi_generator.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_CFI_GENERATOR_H +#define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_CFI_GENERATOR_H + +#include "cfi_generator.h" + +namespace maplebe { +class AArch64GenCfi : public GenCfi { +public: + explicit AArch64GenCfi(CGFunc &func) : GenCfi(func) + { + useFP = func.UseFP(); + if (func.GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { + stackBaseReg = RFP; + } else { + stackBaseReg = useFP ? R29 : RSP; + } + } + ~AArch64GenCfi() override = default; + +private: + void GenerateRegisterSaveDirective(BB &bb, Insn &stackDefInsn) override; + void GenerateRegisterRestoreDirective(BB &bb, Insn &stackRevertInsn) override; + + /* frame pointer(x29) is available as a general-purpose register if useFP is set as false */ + AArch64reg stackBaseReg = RFP; +}; +} /* namespace maplebe */ +#endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_CFI_GENERATOR_H */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h index ce21e9f37b6fa2e50afeb4e0ea2251fa64606c39..8bcab4f7649d7e8cd6aba2e8739c6c8f17e82599 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_cgfunc.h @@ -108,6 +108,18 @@ public: MIRType *LmbcGetAggTyFromCallSite(StmtNode *stmt, std::vector **parmList) const; RegOperand &GetOrCreateResOperand(const BaseNode &parent, PrimType primType); + // struct for delayed phy regs copy in param list + struct RegMapForPhyRegCpy { + RegMapForPhyRegCpy(RegOperand *dReg, PrimType dType, RegOperand *sReg, PrimType sType) + : destReg(dReg), destType(dType), srcReg(sReg), srcType(sType) + { + } + RegOperand *destReg; + PrimType destType; + RegOperand *srcReg; + PrimType srcType; + }; + void IntrinsifyGetAndAddInt(ListOperand &srcOpnds, PrimType pty); void IntrinsifyGetAndSetInt(ListOperand &srcOpnds, PrimType pty); void IntrinsifyCompareAndSwapInt(ListOperand &srcOpnds, PrimType pty); @@ -129,8 +141,7 @@ public: MemOperand *FixLargeMemOpnd(MOperator mOp, MemOperand &memOpnd, uint32 dSize, uint32 opndIdx); uint32 LmbcFindTotalStkUsed(std::vector *paramList); uint32 LmbcTotalRegsUsed(); - void LmbcSelectParmList(ListOperand *srcOpnds, bool isArgReturn); - bool LmbcSmallAggForRet(const BlkassignoffNode &bNode, const Operand *src); + bool LmbcSmallAggForRet(const BaseNode &bNode, const Operand *src, int32 offset = 0, bool skip1 = false); bool LmbcSmallAggForCall(BlkassignoffNode &bNode, const Operand *src, std::vector **parmList); void SelectAggDassign(DassignNode &stmt) override; void SelectIassign(IassignNode &stmt) override; @@ -149,8 +160,8 @@ public: void SelectCondSpecialCase2(const CondGotoNode &stmt, BaseNode &opnd0) override; void SelectGoto(GotoNode &stmt) override; void SelectCall(CallNode &callNode) override; - void SelectIcall(IcallNode &icallNode, Operand &fptrOpnd) override; - void SelectIntrinCall(IntrinsiccallNode &intrinsicCallNode) override; + void SelectIcall(IcallNode &icallNode) override; + void SelectIntrinsicCall(IntrinsiccallNode &intrinsicCallNode) override; Operand *SelectIntrinsicOpWithOneParam(IntrinsicopNode &intrinsicopNode, std::string name) override; Operand *SelectIntrinsicOpWithNParams(IntrinsicopNode &intrinsicopNode, PrimType retType, const std::string &name) override; @@ -169,7 +180,7 @@ public: Operand *SelectCSyncSynchronize(IntrinsicopNode &intrinsicopNode) override; AArch64isa::MemoryOrdering PickMemOrder(std::memory_order memOrder, bool isLdr) const; Operand *SelectCAtomicLoadN(IntrinsicopNode &intrinsicopNode) override; - Operand *SelectCAtomicExchangeN(IntrinsicopNode &intrinsicopNode) override; + Operand *SelectCAtomicExchangeN(const IntrinsiccallNode &intrinsiccallNode) override; Operand *SelectAtomicLoad(Operand &addrOpnd, PrimType primType, AArch64isa::MemoryOrdering memOrder); Operand *SelectCReturnAddress(IntrinsicopNode &intrinsicopNode) override; void SelectMembar(StmtNode &membar) override; @@ -193,7 +204,8 @@ public: PrimType finalBitFieldDestType = kPtyInvalid) override; Operand *SelectIreadoff(const BaseNode &parent, IreadoffNode &ireadoff) override; Operand *SelectIreadfpoff(const BaseNode &parent, IreadFPoffNode &ireadoff) override; - Operand *SelectIntConst(const MIRIntConst &intConst) override; + Operand *SelectIntConst(const MIRIntConst &intConst, const BaseNode &parent) override; + Operand *SelectIntConst(const MIRIntConst &intConst); Operand *HandleFmovImm(PrimType stype, int64 val, MIRConst &mirConst, const BaseNode &parent); Operand *SelectFloatConst(MIRFloatConst &floatConst, const BaseNode &parent) override; Operand *SelectDoubleConst(MIRDoubleConst &doubleConst, const BaseNode &parent) override; @@ -244,7 +256,7 @@ public: AArch64reg regNum, bool &isOutOfRange); void SelectAddAfterInsn(Operand &resOpnd, Operand &o0, Operand &o1, PrimType primType, bool isDest, Insn &insn); bool IsImmediateOffsetOutOfRange(const MemOperand &memOpnd, uint32 bitLen); - bool IsOperandImmValid(MOperator mOp, Operand *o, uint32 opndIdx); + bool IsOperandImmValid(MOperator mOp, Operand *o, uint32 opndIdx) const; Operand *SelectRem(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) override; void SelectDiv(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) override; Operand *SelectDiv(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) override; @@ -282,7 +294,7 @@ public: Operand *SelectLazyLoadStatic(MIRSymbol &st, int64 offset, PrimType primType) override; Operand *SelectLoadArrayClassCache(MIRSymbol &st, int64 offset, PrimType primType) override; RegOperand &SelectCopy(Operand &src, PrimType stype, PrimType dtype) override; - void SelectCopy(Operand &dest, PrimType dtype, Operand &src, PrimType stype); + void SelectCopy(Operand &dest, PrimType dtype, Operand &src, PrimType stype, BaseNode *baseNode = nullptr); void SelectCopyImm(Operand &dest, PrimType dType, ImmOperand &src, PrimType sType); void SelectCopyImm(Operand &dest, ImmOperand &src, PrimType dtype); void SelectLibCall(const std::string &, std::vector &, PrimType, PrimType, bool is2ndRet = false); @@ -434,8 +446,7 @@ public: return GetOrCreatePhysicalRegisterOperand(reg, GetPointerSize() * kBitsPerByte, kRegTyInt); } - RegOperand &GenStructParamIndex(RegOperand &base, const BaseNode &indexExpr, int shift, PrimType baseType, - PrimType targetType); + RegOperand &GenStructParamIndex(RegOperand &base, const BaseNode &indexExpr, int shift, PrimType baseType); void SelectAddrofAfterRa(Operand &result, StImmOperand &stImm, std::vector &rematInsns); MemOperand &GetOrCreateMemOpndAfterRa(const MIRSymbol &symbol, int32 offset, uint32 size, bool needLow12, RegOperand *regOp, std::vector &rematInsns); @@ -664,7 +675,7 @@ public: bool CheckIfSplitOffsetWithAdd(const MemOperand &memOpnd, uint32 bitLen) const; RegOperand *GetBaseRegForSplit(uint32 baseRegNum); - MemOperand &ConstraintOffsetToSafeRegion(uint32 bitLen, const MemOperand &memOpnd); + MemOperand &ConstraintOffsetToSafeRegion(uint32 bitLen, const MemOperand &memOpnd, const MIRSymbol *symbol); MemOperand &SplitOffsetWithAddInstruction(const MemOperand &memOpnd, uint32 bitLen, uint32 baseRegNum = AArch64reg::kRinvalid, bool isDest = false, Insn *insn = nullptr, bool forPair = false); @@ -817,6 +828,15 @@ public: RegOperand &GetZeroOpnd(uint32 size) override; + bool GetStoreFP() const + { + return storeFP; + } + void SetStoreFP(bool val) + { + storeFP = val; + } + private: enum RelationOperator : uint8 { kAND, kIOR, kEOR }; @@ -838,7 +858,7 @@ private: MapleUnorderedMap hashLabelOpndTable; MapleUnorderedMap hashOfstOpndTable; MapleUnorderedMap hashMemOpndTable; - MapleUnorderedMap> stIdx2OverflowResult; + MapleUnorderedMap> stIdx2OverflowResult; /* * Local variables, formal parameters that are passed via registers * need offset adjustment after callee-saved registers are known. @@ -874,6 +894,7 @@ private: uint32 alignPow = 5; /* function align pow defaults to 5 i.e. 2^5*/ LmbcArgInfo *lmbcArgInfo = nullptr; MIRType *lmbcCallReturnType = nullptr; + bool storeFP = false; void SelectLoadAcquire(Operand &dest, PrimType dtype, Operand &src, PrimType stype, AArch64isa::MemoryOrdering memOrd, bool isDirect); @@ -915,8 +936,9 @@ private: RegOperand *SelectParmListDreadAccessField(const MIRSymbol &sym, FieldID fieldID, const CCLocInfo &ploc, int32 offset, uint32 parmNum); void CreateCallStructParamPassByReg(regno_t reg, MemOperand &memOpnd, ListOperand &srcOpnds, fpParamState state); - void CreateCallStructParamMemcpy(const MIRSymbol *sym, RegOperand *addropnd, uint32 structSize, int32 copyOffset, - int32 fromOffset); + void CreateCallStructParamMemcpy(const MIRSymbol &sym, uint32 structSize, int32 copyOffset, int32 fromOffset); + void CreateCallStructParamMemcpy(RegOperand &addrOpnd, uint32 structSize, int32 copyOffset, int32 fromOffset); + RegOperand *CreateCallStructParamCopyToStack(uint32 numMemOp, const MIRSymbol *sym, RegOperand *addrOpd, int32 copyOffset, int32 fromOffset, const CCLocInfo &ploc); void SelectParmListDreadSmallAggregate(const MIRSymbol &sym, MIRType &structType, ListOperand &srcOpnds, @@ -964,6 +986,7 @@ private: bool GenerateCompareWithZeroInstruction(Opcode jmpOp, Opcode cmpOp, bool is64Bits, PrimType primType, LabelOperand &targetOpnd, Operand &opnd0); void GenCVaStartIntrin(RegOperand &opnd, uint32 stkSize); + void SelectCDIVException(); void SelectCVaStart(const IntrinsiccallNode &intrnNode); void SelectOverFlowCall(const IntrinsiccallNode &intrnNode); void SelectCAtomicStoreN(const IntrinsiccallNode &intrinsiccallNode); @@ -1012,6 +1035,8 @@ private: RegOperand *PrepareMemcpyParamOpnd(bool isLo12, const MIRSymbol &symbol, int64 offsetVal, RegOperand &BaseReg); RegOperand *PrepareMemcpyParamOpnd(int64 offset, Operand &exprOpnd); RegOperand *PrepareMemcpyParamOpnd(uint64 copySize); + MemOperand &CreateMemOpndForStatic(const MIRSymbol &symbol, int64 offset, uint32 size, bool needLow12, + RegOperand *regOp); Insn *AggtStrLdrInsert(bool bothUnion, Insn *lastStrLdr, Insn &newStrLdr); LabelIdx GetLabelInInsn(Insn &insn) override { diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_imm_valid.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_imm_valid.h new file mode 100644 index 0000000000000000000000000000000000000000..cfd53465fb4068840d5bd3e73ed1a7d97f4d30dd --- /dev/null +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_imm_valid.h @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_IMM_VALID_H +#define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_IMM_VALID_H + +#include "common_utils.h" +#include "types_def.h" + +namespace maplebe { +inline bool IsBitSizeImmediate(uint64 val, uint32 bitLen, uint32 nLowerZeroBits) +{ + // mask1 is a 64bits number that is all 1 shifts left size bits + const uint64 mask1 = 0xffffffffffffffffUL << bitLen; + // mask2 is a 64 bits number that nlowerZeroBits are all 1, higher bits aro all 0 + uint64 mask2 = (1UL << static_cast(nLowerZeroBits)) - 1UL; + return (mask2 & val) == 0UL && (mask1 & ((static_cast(val)) >> nLowerZeroBits)) == 0UL; +}; + +// This is a copy from "operand.cpp", temporary fix for me_slp.cpp usage of this file +// was IsMoveWidableImmediate +inline bool IsMoveWidableImmediateCopy(uint64 val, uint32 bitLen) +{ + // When #imm is FFFFFFFF, ~val should return true, because ~val is 0, and it should be valid. + // But ~val and (~val & 0xffffffff) both will be 0, it will return false, so we judge this situation alone. + if (val == 0 || val == 0xffffffff) { + return true; + } + if (bitLen == k64BitSize) { + // 0xHHHH000000000000 or 0x0000HHHH00000000, return true + if (((val & ((static_cast(0xffff)) << k48BitSize)) == val) || + ((val & ((static_cast(0xffff)) << k32BitSize)) == val)) { + return true; + } + } else { + // get lower 32 bits + val &= static_cast(0xffffffff); + // If lower 32 bits are all 0, but higher 32 bits have 1, val will be 1 and return true, but it is false in + // fact. + if (val == 0) { + return false; + } + } + // 0x00000000HHHH0000 or 0x000000000000HHHH, return true + return ((val & ((static_cast(0xffff)) << k16BitSize)) == val || (val & static_cast(0xffff)) == val); +} +namespace aarch64 { +bool IsBitmaskImmediate(uint64 val, uint32 bitLen); +} // namespace aarch64 + +using namespace aarch64; +inline bool IsSingleInstructionMovable32(int64 value) +{ + // When value & ffffffff00000000 is 0, all high 32-bits are 0. + // When value & ffffffff00000000 is ffffffff00000000, all high 32-bits are 1. + // High 32-bits should be all 0 or all 1, when it comes to mov w0, #imm. + if ((static_cast(value) & 0xffffffff00000000ULL) != 0 && + (static_cast(value) & 0xffffffff00000000ULL) != 0xffffffff00000000ULL) { + return false; + } + constexpr uint32 bitLen = 32; + return (IsMoveWidableImmediateCopy(static_cast(value), bitLen) || + IsMoveWidableImmediateCopy(~static_cast(value), bitLen) || + IsBitmaskImmediate(static_cast(value), bitLen)); +} + +inline bool IsSingleInstructionMovable64(int64 value) +{ + constexpr uint32 bitLen = 64; + return (IsMoveWidableImmediateCopy(static_cast(value), bitLen) || + IsMoveWidableImmediateCopy(~static_cast(value), bitLen) || + IsBitmaskImmediate(static_cast(value), bitLen)); +} + +inline bool Imm12BitValid(int64 value) +{ + bool result = IsBitSizeImmediate(static_cast(value), kMaxImmVal12Bits, 0); + // for target linux-aarch64-gnu + result = result || IsBitSizeImmediate(static_cast(value), kMaxImmVal12Bits, kMaxImmVal12Bits); + return result; +} + +// For the 32-bit variant: is the bitmask immediate +inline bool Imm12BitMaskValid(int64 value) +{ + if (value == 0 || static_cast(value) == -1) { + return false; + } + return IsBitmaskImmediate(static_cast(value), k32BitSize); +} + +inline bool Imm13BitValid(int64 value) +{ + bool result = IsBitSizeImmediate(static_cast(value), kMaxImmVal13Bits, 0); + // for target linux-aarch64-gnu + result = result || IsBitSizeImmediate(static_cast(value), kMaxImmVal13Bits, kMaxImmVal13Bits); + return result; +} + +// For the 64-bit variant: is the bitmask immediate +inline bool Imm13BitMaskValid(int64 value) +{ + if (value == 0 || static_cast(value) == -1) { + return false; + } + return IsBitmaskImmediate(static_cast(value), k64BitSize); +} + +inline bool Imm16BitValid(int64 value) +{ + bool result = IsBitSizeImmediate(static_cast(value), kMaxImmVal16Bits, 0); + // for target linux-aarch64-gnu + // aarch64 assembly takes up to 24-bits immediate, generating + // either cmp or cmp with shift 12 encoding + result = result || IsBitSizeImmediate(static_cast(value), kMaxImmVal12Bits, kMaxImmVal12Bits); + return result; +} + +// For the 32-bit variant: is the shift amount, in the range 0 to 31, opnd input is bitshiftopnd +inline bool BitShift5BitValid(uint32 value) +{ + bool result = IsBitSizeImmediate(static_cast(value), kMaxImmVal5Bits, 0); + return result; +} + +// For the 64-bit variant: is the shift amount, in the range 0 to 63, opnd input is bitshiftopnd +inline bool BitShift6BitValid(uint32 value) +{ + bool result = IsBitSizeImmediate(static_cast(value), kMaxImmVal6Bits, 0); + return result; +} + +// For the 32-bit variant: is the shift amount, in the range 0 to 31, opnd input is immopnd +inline bool BitShift5BitValidImm(int64 value) +{ + bool result = IsBitSizeImmediate(static_cast(value), kMaxImmVal5Bits, 0); + return result; +} + +// For the 64-bit variant: is the shift amount, in the range 0 to 63, opnd input is immopnd +inline bool BitShift6BitValidImm(int64 value) +{ + bool result = IsBitSizeImmediate(static_cast(value), kMaxImmVal6Bits, 0); + return result; +} + +// Is a 16-bit unsigned immediate, in the range 0 to 65535, used by BRK +inline bool Imm16BitValidImm(int64 value) +{ + bool result = IsBitSizeImmediate(static_cast(value), kMaxImmVal16Bits, 0); + return result; +} + +// Is the flag bit specifier, an immediate in the range 0 to 15, used by CCMP +inline bool Nzcv4BitValid(int64 value) +{ + bool result = IsBitSizeImmediate(static_cast(value), k4BitSize, 0); + return result; +} + +// For the 32-bit variant: is the bit number of the lsb of the source bitfield, in the range 0 to 31 +inline bool Lsb5BitValid(int64 value) +{ + bool result = IsBitSizeImmediate(static_cast(value), kMaxImmVal5Bits, 0); + return result; +} + +// For the 32-bit variant: is the width of the bitfield, in the range 1 to 32- +inline bool Width5BitValid(int64 value, int64 lsb) +{ + constexpr int64 offset = 32; + return (value >= 1) && (value <= offset - lsb); +} + +// For the 32-bit variant: is the width of the bitfield, in the range 1 to 32, is used for only width verified +inline bool Width5BitOnlyValid(int64 value) +{ + constexpr int64 offset = 32; + return (value >= 1) && (value <= offset); +} + +// For the 64-bit variant: is the bit number of the lsb of the source bitfield, in the range 0 to 63 +inline bool Lsb6BitValid(int64 value) +{ + bool result = IsBitSizeImmediate(static_cast(value), kMaxImmVal6Bits, 0); + return result; +} + +// For the 64-bit variant: is the width of the bitfield, in the range 1 to 64- +inline bool Width6BitValid(int64 value, int64 lsb) +{ + constexpr int64 offset = 64; + return (value >= 1) && (value <= offset - lsb); +} + +// For the 64-bit variant: is the width of the bitfield, in the range 1 to 64, is used for only width verified +inline bool Width6BitOnlyValid(int64 value) +{ + constexpr int64 offset = 64; + return (value >= 1) && (value <= offset); +} + +// Is the left shift amount to be applied after extension in the range 0 to 4, uint32 means value non-negative +inline bool ExtendShift0To4Valid(uint32 value) +{ + return (value <= k4BitSize); +} + +// Is the optional left shift to apply to the immediate, it can have the values: 0, 12 +inline bool LeftShift12Valid(uint32 value) +{ + return value == k0BitSize || value == k12BitSize; +} + +// For the 32-bit variant: is the amount by which to shift the immediate left, either 0 or 16 +inline bool ImmShift32Valid(uint32 value) +{ + return value == k0BitSize || value == k16BitSize; +} + +// For the 64-bit variant: is the amount by which to shift the immediate left, either 0, 16, 32 or 48 +inline bool ImmShift64Valid(uint32 value) +{ + return value == k0BitSize || value == k16BitSize || value == k32BitSize || value == k48BitSize; +} + +inline bool IsSIMMValid(int64 value) +{ + return (value <= kMaxSimm32) && (value >= kMinSimm32); +} + +inline bool IsPIMMValid(int64 value, uint wordSize) +{ + if ((value >= k0BitSize) && (value <= kMaxPimm[wordSize])) { + uint64 mask = (1U << wordSize) - 1U; + return (static_cast(value) & mask) > 0 ? false : true; + } + return false; +} + +// Used for backend str/ldr memopnd offset judgment +inline bool StrLdrInsnSignedOfstValid(int64 value, uint wordSize, bool IsIntactIndexed) +{ + return IsSIMMValid(value) || (IsPIMMValid(value, wordSize) && IsIntactIndexed); +} + +// 8bit : 0 +// halfword : 1 +// 32bit - word : 2 +// 64bit - word : 3 +// 128bit- word : 4 +inline bool StrLdrSignedOfstValid(int64 value, uint wordSize) +{ + return IsSIMMValid(value) || IsPIMMValid(value, wordSize); +} + +inline bool StrLdr8ImmValid(int64 value) +{ + return StrLdrSignedOfstValid(value, 0); +} + +inline bool StrLdr16ImmValid(int64 value) +{ + return StrLdrSignedOfstValid(value, k1ByteSize); +} + +inline bool StrLdr32ImmValid(int64 value) +{ + return StrLdrSignedOfstValid(value, k2ByteSize); +} + +inline bool StrLdr32PairImmValid(int64 value) +{ + constexpr int immValidOffset = 3; + if ((value <= kMaxSimm32Pair) && (value >= kMinSimm32)) { + return (static_cast(value) & immValidOffset) > 0 ? false : true; + } + return false; +} + +inline bool StrLdr64ImmValid(int64 value) +{ + return StrLdrSignedOfstValid(value, k3ByteSize); +} + +inline bool StrLdr64PairImmValid(int64 value) +{ + constexpr int immValidOffset = 7; + if (value <= kMaxSimm64Pair && (value >= kMinSimm64)) { + return (static_cast(value) & immValidOffset) > 0 ? false : true; + } + return false; +} + +inline bool StrLdr128ImmValid(int64 value) +{ + return StrLdrSignedOfstValid(value, k4ByteSize); +} + +inline bool StrLdr128PairImmValid(int64 value) +{ + if (value < k1024BitSize && (value >= kNegative1024BitSize)) { + return (static_cast(value) & 0xf) > 0 ? false : true; + } + return false; +} +} // namespace maplebe + +#endif // MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_IMM_VALID_H diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_isa.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_isa.h index aa86c0b17c3fe641ef4470ff5d85e2c01ff8158e..c78b8d7af384facda70b914c1e5497d596f7d58a 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_isa.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_isa.h @@ -162,11 +162,19 @@ static inline bool IsPseudoInstruction(MOperator mOp) */ uint32 GetJumpTargetIdx(const Insn &insn); +bool IsSub(const Insn &insn); + +MOperator GetMopSub2Subs(const Insn &insn); + MOperator FlipConditionOp(MOperator flippedOp); // Function: for immediate verification, memopnd ofstvalue is returned from opnd input. // It's worth noting that 0 will be returned when kBOR memopnd is input. int64 GetMemOpndOffsetValue(Operand *o); + +int32 GetTail0BitNum(int64 val); + +int32 GetHead0BitNum(int64 val); } /* namespace AArch64isa */ /* diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_md.def b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_md.def index 7b31b7485ea00a1ab3ed58c3f1f983a03b1e72f0..e15468abcaa01357d23bb1d95143d3d0367a5ec9 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_md.def +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_md.def @@ -14,7 +14,7 @@ */ /* InsnDesc format: - * {mop, opndMD, properties, latency, name, format, atomicNum, validFunc(nullptr)} + * {mop, opndMD, properties, latency, name, format, atomicNum, validFunc(nullptr), splitFunc(nullptr), encodeType, encode} */ /* AARCH64 MOVES */ @@ -23,9 +23,9 @@ DEFINE_MOP(MOP_xmovrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS},ISMOVE,kLtAlu,"mo /* MOP_wmovrr */ DEFINE_MOP(MOP_wmovrr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS},ISMOVE,kLtAlu,"mov","0,1",1,kMovReg,0x00000000) /* MOP_wmovri32 */ -DEFINE_MOP(MOP_wmovri32, {&OpndDesc::Reg32ID,&OpndDesc::Imm32},ISMOVE,kLtAlu,"mov","0,1",1,kMovImm,0x00000000) +DEFINE_MOP(MOP_wmovri32, {&OpndDesc::Reg32ID,&OpndDesc::Imm32},ISMOVE,kLtAlu,"mov","0,1",1,MOP_wmovri32Valid,MOP_wmovri32Split,kMovImm,0x00000000) /* MOP_xmovri64 */ -DEFINE_MOP(MOP_xmovri64, {&OpndDesc::Reg64ID,&OpndDesc::Imm64},ISMOVE,kLtAlu,"mov","0,1",1,kMovImm,0x00000000) +DEFINE_MOP(MOP_xmovri64, {&OpndDesc::Reg64ID,&OpndDesc::Imm64},ISMOVE,kLtAlu,"mov","0,1",1,MOP_xmovri64Valid, MOP_xmovri64Split,kMovImm,0x00000000) /* MOP_xmovrr_uxtw -- Remove Redundant uxtw -- used in globalopt:UxtwMovPattern */ DEFINE_MOP(MOP_xmovrr_uxtw, {&OpndDesc::Reg64ID,&OpndDesc::Reg32IS},ISMOVE,kLtAlu,"mov","0,1",1) @@ -57,27 +57,33 @@ DEFINE_MOP(MOP_xadrpl12, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Liter /* AARCH64 Arithmetic: add */ /* MOP_xaddrrr */ DEFINE_MOP(MOP_xaddrrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS},0,kLtAlu,"add","0,1,2",1,kAddSubReg,0x8B000000) +/* MOP_xaddsrrr */ +DEFINE_MOP(MOP_xaddsrrr, {&OpndDesc::CCD, &OpndDesc::Reg64ID, &OpndDesc::Reg64IS, &OpndDesc::Reg64IS}, 0, kLtAlu, "adds", "1,2,3", 1) /* MOP_xaddrrrs */ -DEFINE_MOP(MOP_xaddrrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAluShift,"add","0,1,2,3",1,kAddSubShiftReg,0x8B000000) +DEFINE_MOP(MOP_xaddrrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAluShift,"add","0,1,2,3",1,MOP_xaddrrrsValid,kAddSubShiftReg,0x8B000000) /* MOP_xxwaddrrre */ -DEFINE_MOP(MOP_xxwaddrrre, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAluShift,"add","0,1,2,3",1,kAddSubExtendReg,0x8B200000) +DEFINE_MOP(MOP_xxwaddrrre, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAluShift,"add","0,1,2,3",1,MOP_xxwaddrrreValid,kAddSubExtendReg,0x8B200000) /* MOP_xaddrri24 */ -DEFINE_MOP(MOP_xaddrri24, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtShift,"add","0,1,2,3",1,Imm12BitValid,kAddSubShiftImm,0x91000000) +DEFINE_MOP(MOP_xaddrri24, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtShift,"add","0,1,2,3",1,MOP_xaddrri24Valid,MOP_xaddrri24Split,kAddSubShiftImm,0x91000000) /* MOP_xaddrri12 */ -DEFINE_MOP(MOP_xaddrri12, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12},0,kLtAlu,"add","0,1,2",1,Imm12BitValid,kAddSubImm,0x91000000) +DEFINE_MOP(MOP_xaddrri12, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12},0,kLtAlu,"add","0,1,2",1,MOP_xaddrri12Valid,MOP_xaddrri12Split,kAddSubImm,0x91000000) +/* MOP_xaddsrri12 */ +DEFINE_MOP(MOP_xaddsrri12, {&OpndDesc::CCD, &OpndDesc::Reg64ID, &OpndDesc::Reg64IS, &OpndDesc::Imm12}, 0, kLtAlu, "adds", "1,2,3", 1, MOP_xaddsrri12Valid,MOP_xaddsrri12Split) /* MOP_waddrrr */ DEFINE_MOP(MOP_waddrrr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS},0,kLtAlu,"add","0,1,2",1,kAddSubReg,0xb000000) /* MOP_waddrrrs */ -DEFINE_MOP(MOP_waddrrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAluShift,"add","0,1,2,3",1,kAddSubShiftReg,0xb000000) +DEFINE_MOP(MOP_waddrrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAluShift,"add","0,1,2,3",1,MOP_waddrrrsValid, kAddSubShiftReg,0xb000000) /* MOP_waddsrrr */ DEFINE_MOP(MOP_waddsrrr, {&OpndDesc::CCD,&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS},0,kLtAlu,"adds","1,2,3",1, kAddSubReg, 0x2b000000) /* MOP_xxwaddrrre */ -DEFINE_MOP(MOP_wwwaddrrre, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAluShift,"add","0,1,2,3",1,kAddSubExtendReg, 0xB200000) +DEFINE_MOP(MOP_wwwaddrrre, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAluShift,"add","0,1,2,3",1,MOP_wwwaddrrreValid,kAddSubExtendReg, 0xB200000) /* MOP_waddrri24 */ -DEFINE_MOP(MOP_waddrri24, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtAluShift,"add","0,1,2,3",1,Imm12BitValid,kAddSubShiftImm,0x11000000) +DEFINE_MOP(MOP_waddrri24, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtAluShift,"add","0,1,2,3",1,MOP_waddrri24Valid,MOP_waddrri24Split,kAddSubShiftImm,0x11000000) /* MOP_waddrri12 */ -DEFINE_MOP(MOP_waddrri12, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"add","0,1,2",1,Imm12BitValid,kAddSubImm,0x11000000) +DEFINE_MOP(MOP_waddrri12, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"add","0,1,2",1,MOP_waddrri12Valid,MOP_waddrri12Split,kAddSubImm,0x11000000) +/* MOP_waddsrri12 */ +DEFINE_MOP(MOP_waddsrri12, {&OpndDesc::CCD, &OpndDesc::Reg32ID, &OpndDesc::Reg32IS, &OpndDesc::Imm12}, 0, kLtAlu, "adds", "1,2,3", 1,MOP_waddsrri12Valid,MOP_waddsrri12Split) /* MOP_dadd */ DEFINE_MOP(MOP_dadd, {&OpndDesc::Reg64FD,&OpndDesc::Reg64FS,&OpndDesc::Reg64FS},0,kLtFpalu,"fadd","0,1,2",1,kFloatDataProcessing2,0x1e602800) /* MOP_sadd */ @@ -89,37 +95,37 @@ DEFINE_MOP(MOP_xsubrrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64I /* MOP_xsubsrrr */ DEFINE_MOP(MOP_xsubsrrr, {&OpndDesc::CCD, &OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS},0,kLtAlu,"subs","1,2,3",1, kAddSubReg, 0xeb000000) /* MOP_xsubrrrs */ -DEFINE_MOP(MOP_xsubrrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAluShift,"sub","0,1,2,3",1,kAddSubShiftReg, 0xcb000000) +DEFINE_MOP(MOP_xsubrrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAluShift,"sub","0,1,2,3",1,MOP_xsubrrrsValid,kAddSubShiftReg, 0xcb000000) /* MOP_xxwsubrrre */ DEFINE_MOP(MOP_xxwsubrrre, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAluShift,"sub","0,1,2,3",1, kAddSubExtendReg, 0xcb200000) /* MOP_xsubsrrrs */ -DEFINE_MOP(MOP_xsubsrrrs, {&OpndDesc::CCD, &OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAluShift,"subs","1,2,3,4",1, kAddSubShiftReg, 0xeb000000) +DEFINE_MOP(MOP_xsubsrrrs, {&OpndDesc::CCD, &OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAluShift,"subs","1,2,3,4",1,MOP_xsubsrrrsValid,kAddSubShiftReg, 0xeb000000) /* MOP_xsubrri24 */ -DEFINE_MOP(MOP_xsubrri24, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtAluShift,"sub","0,1,2,3",1,Imm12BitValid,kAddSubShiftImm,0xd1000000) +DEFINE_MOP(MOP_xsubrri24, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtAluShift,"sub","0,1,2,3",1,MOP_xsubrri24Valid, MOP_xsubrri24Split,kAddSubShiftImm,0xd1000000) /* MOP_xsubsrri24 */ -DEFINE_MOP(MOP_xsubsrri24, {&OpndDesc::CCD, &OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtAluShift,"subs","1,2,3,4",1,Imm12BitValid, kAddSubShiftImm, 0xf1000000) +DEFINE_MOP(MOP_xsubsrri24, {&OpndDesc::CCD, &OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtAluShift,"subs","1,2,3,4",1,MOP_xsubsrri24Valid,kAddSubShiftImm, 0xf1000000) /* MOP_xsubrri12 */ -DEFINE_MOP(MOP_xsubrri12, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12},0,kLtAlu,"sub","0,1,2",1,Imm12BitValid,kAddSubImm,0xd1000000) +DEFINE_MOP(MOP_xsubrri12, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12},0,kLtAlu,"sub","0,1,2",1,MOP_xsubrri12Valid,MOP_xsubrri12Split,kAddSubImm,0xd1000000) /* MOP_xsubsrri12 */ -DEFINE_MOP(MOP_xsubsrri12, {&OpndDesc::CCD, &OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12},0,kLtAlu,"subs","1,2,3",1,Imm12BitValid, kAddSubImm, 0xf1000000) +DEFINE_MOP(MOP_xsubsrri12, {&OpndDesc::CCD, &OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm12},0,kLtAlu,"subs","1,2,3",1,MOP_xsubsrri12Valid,MOP_xsubsrri12Split, kAddSubImm, 0xf1000000) /* MOP_wsubrrr */ DEFINE_MOP(MOP_wsubrrr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS},0,kLtAlu,"sub","0,1,2",1,kAddSubReg,0x4b000000) /* MOP_wsubsrrr */ DEFINE_MOP(MOP_wsubsrrr, {&OpndDesc::CCD,&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS},0,kLtAlu,"subs","1,2,3",1, kAddSubReg, 0x6b000000) /* MOP_wsubrrrs */ -DEFINE_MOP(MOP_wsubrrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAluShift,"sub","0,1,2,3",1, kAddSubShiftReg, 0x4b000000) +DEFINE_MOP(MOP_wsubrrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAluShift,"sub","0,1,2,3",1,MOP_wsubrrrsValid,kAddSubShiftReg, 0x4b000000) /* MOP_wwwsubrrre */ DEFINE_MOP(MOP_wwwsubrrre, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAluShift,"sub","0,1,2,3",1, kAddSubExtendReg, 0x4b200000) /* MOP_wsubsrrrs */ -DEFINE_MOP(MOP_wsubsrrrs, {&OpndDesc::CCD,&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAluShift,"subs","1,2,3,4",1, kAddSubShiftReg, 0x6b000000) +DEFINE_MOP(MOP_wsubsrrrs, {&OpndDesc::CCD,&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAluShift,"subs","1,2,3,4",1,MOP_wsubsrrrsValid,kAddSubShiftReg, 0x6b000000) /* MOP_wsubrri24 */ -DEFINE_MOP(MOP_wsubrri24, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtAluShift,"sub","0,1,2,3",1,Imm12BitValid,kAddSubShiftImm,0x51000000) +DEFINE_MOP(MOP_wsubrri24, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtAluShift,"sub","0,1,2,3",1,MOP_wsubrri24Valid,MOP_wsubrri24Split,kAddSubShiftImm,0x51000000) /* MOP_wsubsrri24 */ -DEFINE_MOP(MOP_wsubsrri24, {&OpndDesc::CCD,&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtAluShift,"subs","1,2,3,4",1,Imm12BitValid, kAddSubShiftImm, 0x71000000) +DEFINE_MOP(MOP_wsubsrri24, {&OpndDesc::CCD,&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12,&OpndDesc::Lsl12},0,kLtAluShift,"subs","1,2,3,4",1,MOP_wsubsrri24Valid,kAddSubShiftImm, 0x71000000) /* MOP_wsubrri12 */ -DEFINE_MOP(MOP_wsubrri12, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"sub","0,1,2",1,Imm12BitValid,kAddSubImm,0x51000000) +DEFINE_MOP(MOP_wsubrri12, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"sub","0,1,2",1,MOP_wsubrri12Valid,MOP_wsubrri12Split,kAddSubImm,0x51000000) /* MOP_wsubsrri12 */ -DEFINE_MOP(MOP_wsubsrri12, {&OpndDesc::CCD,&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"subs","1,2,3",1,Imm12BitValid, kAddSubImm, 0x71000000) +DEFINE_MOP(MOP_wsubsrri12, {&OpndDesc::CCD,&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"subs","1,2,3",1,MOP_wsubsrri12Valid,MOP_wsubsrri12Split,kAddSubImm, 0x71000000) /* MOP_dsub */ DEFINE_MOP(MOP_dsub, {&OpndDesc::Reg64FD,&OpndDesc::Reg64FS,&OpndDesc::Reg64FS},0,kLtFpalu,"fsub","0,1,2",1,kFloatDataProcessing2,0x1e603800) /* MOP_ssub */ @@ -256,15 +262,15 @@ DEFINE_MOP(MOP_xcsinvrrrc, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg /* MOP_xandrrr */ DEFINE_MOP(MOP_xandrrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS},0,kLtAlu,"and","0,1,2",1,kLogicalReg,0x8a000000) /* MOP_xandrrrs */ -DEFINE_MOP(MOP_xandrrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAluShift,"and","0,1,2,3",1,kLogicalReg,0x8a000000) +DEFINE_MOP(MOP_xandrrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAluShift,"and","0,1,2,3",1,MOP_xandrrrsValid,kLogicalReg,0x8a000000) /* MOP_xandrri13 */ -DEFINE_MOP(MOP_xandrri13, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm13},0,kLtAlu,"and","0,1,2",1,Imm13BitMaskValid,kLogicalImm,0x92000000) +DEFINE_MOP(MOP_xandrri13, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm13},0,kLtAlu,"and","0,1,2",1,MOP_xandrri13Valid,kLogicalImm,0x92000000) /* MOP_wandrrr */ DEFINE_MOP(MOP_wandrrr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS},0,kLtAlu,"and","0,1,2",1,kLogicalReg,0xa000000) /* MOP_wandrrrs */ -DEFINE_MOP(MOP_wandrrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAluShift,"and","0,1,2,3",1,kLogicalReg,0xa000000) +DEFINE_MOP(MOP_wandrrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAluShift,"and","0,1,2,3",1,MOP_wandrrrsValid,kLogicalReg,0xa000000) /* MOP_wandrri12 */ -DEFINE_MOP(MOP_wandrri12, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"and","0,1,2",1,Imm12BitMaskValid,kLogicalImm,0x12000000) +DEFINE_MOP(MOP_wandrri12, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"and","0,1,2",1,MOP_wandrri12Valid,kLogicalImm,0x12000000) /* MOP_xbicrrr */ DEFINE_MOP(MOP_xbicrrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS},0,kLtAlu,"bic","0,1,2",1, kLogicalReg, 0x8a200000) @@ -274,28 +280,28 @@ DEFINE_MOP(MOP_wbicrrr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32I /* MOP_xiorrrr */ DEFINE_MOP(MOP_xiorrrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS},0,kLtAlu,"orr","0,1,2",1,kLogicalReg,0xaa000000) /* MOP_xiorrrrs */ -DEFINE_MOP(MOP_xiorrrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAlu,"orr","0,1,2,3",1,kLogicalReg,0xaa000000) +DEFINE_MOP(MOP_xiorrrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAlu,"orr","0,1,2,3",1,MOP_xiorrrrsValid,kLogicalReg,0xaa000000) /* MOP_xiorrri13 */ -DEFINE_MOP(MOP_xiorrri13, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm13},0,kLtAlu,"orr","0,1,2",1,Imm13BitMaskValid,kLogicalImm,0xb2000000) +DEFINE_MOP(MOP_xiorrri13, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm13},0,kLtAlu,"orr","0,1,2",1,MOP_xiorrri13Valid,kLogicalImm,0xb2000000) /* MOP_wiorrrr */ DEFINE_MOP(MOP_wiorrrr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS},0,kLtAlu,"orr","0,1,2",1,kLogicalReg,0x2a000000) /* MOP_wiorrrrs */ -DEFINE_MOP(MOP_wiorrrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAlu,"orr","0,1,2,3",1,kLogicalReg,0x2a000000) +DEFINE_MOP(MOP_wiorrrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAlu,"orr","0,1,2,3",1,MOP_wiorrrrsValid,kLogicalReg,0x2a000000) /* MOP_wiorrri12 */ -DEFINE_MOP(MOP_wiorrri12, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"orr","0,1,2",1,Imm12BitMaskValid,kLogicalImm,0x32000000) +DEFINE_MOP(MOP_wiorrri12, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"orr","0,1,2",1,MOP_wiorrri12Valid,kLogicalImm,0x32000000) /* MOP_xeorrrr */ DEFINE_MOP(MOP_xeorrrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS},0,kLtAlu,"eor","0,1,2",1,kLogicalReg,0xca000000) /* MOP_xeorrrrs */ -DEFINE_MOP(MOP_xeorrrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAlu,"eor","0,1,2,3",1,kLogicalReg,0xca000000) +DEFINE_MOP(MOP_xeorrrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAlu,"eor","0,1,2,3",1,MOP_xeorrrrsValid,kLogicalReg,0xca000000) /* MOP_xeorrri13 */ -DEFINE_MOP(MOP_xeorrri13, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm13},0,kLtAlu,"eor","0,1,2",1,Imm13BitMaskValid,kLogicalImm,0xd2000000) +DEFINE_MOP(MOP_xeorrri13, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm13},0,kLtAlu,"eor","0,1,2",1,MOP_xeorrri13Valid,kLogicalImm,0xd2000000) /* MOP_weorrrr */ DEFINE_MOP(MOP_weorrrr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS},0,kLtAlu,"eor","0,1,2",1,kLogicalReg,0x4a000000) /* MOP_weorrrrs */ -DEFINE_MOP(MOP_weorrrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAlu,"eor","0,1,2,3",1,kLogicalReg,0x4a000000) +DEFINE_MOP(MOP_weorrrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAlu,"eor","0,1,2,3",1,MOP_weorrrrsValid,kLogicalReg,0x4a000000) /* MOP_weorrri12 */ -DEFINE_MOP(MOP_weorrri12, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"eor","0,1,2",1,Imm12BitMaskValid,kLogicalImm,0x52000000) +DEFINE_MOP(MOP_weorrri12, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"eor","0,1,2",1,MOP_weorrri12Valid,kLogicalImm,0x52000000) /* MOP_xnotrr */ DEFINE_MOP(MOP_xnotrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS},0,kLtAlu,"mvn","0,1",1,kLogicalReg,0xaa2003e0) @@ -335,40 +341,40 @@ DEFINE_MOP(MOP_wmnegrrr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32 DEFINE_MOP(MOP_xmnegrrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS},0,kLtMul,"mneg","0,1,2",1, kDataProcess3Src, 0x9b00fc00) /* MOP_wubfxrri5i5 */ -DEFINE_MOP(MOP_wubfxrri5i5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm5,&OpndDesc::Imm5},0,kLtAluShift,"ubfx","0,1,2,3",1,kBitfield,0x53000000) +DEFINE_MOP(MOP_wubfxrri5i5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm5,&OpndDesc::Imm5},0,kLtAluShift,"ubfx","0,1,2,3",1,MOP_wubfxrri5i5Valid,kBitfield,0x53000000) /* MOP_xubfxrri6i6 */ -DEFINE_MOP(MOP_xubfxrri6i6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6,&OpndDesc::Imm6},0,kLtAluShift,"ubfx","0,1,2,3",1,kBitfield,0xd3400000) +DEFINE_MOP(MOP_xubfxrri6i6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6,&OpndDesc::Imm6},0,kLtAluShift,"ubfx","0,1,2,3",1,MOP_xubfxrri6i6Valid,kBitfield,0xd3400000) /* MOP_wsbfxrri5i5 -- Signed Bitfield Extract */ -DEFINE_MOP(MOP_wsbfxrri5i5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm5,&OpndDesc::Imm5},0,kLtAluShift,"sbfx","0,1,2,3",1,kBitfield,0x13000000) +DEFINE_MOP(MOP_wsbfxrri5i5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm5,&OpndDesc::Imm5},0,kLtAluShift,"sbfx","0,1,2,3",1,MOP_wsbfxrri5i5Valid,kBitfield,0x13000000) /* MOP_xsbfxrri6i6 */ -DEFINE_MOP(MOP_xsbfxrri6i6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6,&OpndDesc::Imm6},0,kLtAluShift,"sbfx","0,1,2,3",1,kBitfield,0x93400000) +DEFINE_MOP(MOP_xsbfxrri6i6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6,&OpndDesc::Imm6},0,kLtAluShift,"sbfx","0,1,2,3",1,MOP_xsbfxrri6i6Valid,kBitfield,0x93400000) /* MOP_wubfizrri5i5 -- Unsigned Bitfield Insert in Zero */ -DEFINE_MOP(MOP_wubfizrri5i5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm5,&OpndDesc::Imm5},0,kLtAluShift,"ubfiz","0,1,2,3",1,kBitfield,0x53000000) +DEFINE_MOP(MOP_wubfizrri5i5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm5,&OpndDesc::Imm5},0,kLtAluShift,"ubfiz","0,1,2,3",1,MOP_wubfizrri5i5Valid,kBitfield,0x53000000) /* MOP_xubfizrri6i6 */ -DEFINE_MOP(MOP_xubfizrri6i6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6,&OpndDesc::Imm6},0,kLtAluShift,"ubfiz","0,1,2,3",1,kBitfield,0xd3400000) +DEFINE_MOP(MOP_xubfizrri6i6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6,&OpndDesc::Imm6},0,kLtAluShift,"ubfiz","0,1,2,3",1,MOP_xubfizrri6i6Valid,kBitfield,0xd3400000) /* MOP_xsbfizrri6i6 Signed Bitfield Insert in Zero */ -DEFINE_MOP(MOP_xsbfizrri6i6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6,&OpndDesc::Imm6},0,kLtAluShift,"sbfiz","0,1,2,3",1, kBitfield, 0x13000000) +DEFINE_MOP(MOP_xsbfizrri6i6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6,&OpndDesc::Imm6},0,kLtAluShift,"sbfiz","0,1,2,3",1,MOP_xsbfizrri6i6Valid,kBitfield, 0x13000000) /* MOP_wbfirri5i5 -- Bitfield Insert */ -DEFINE_MOP(MOP_wbfirri5i5, {&OpndDesc::Reg32IDS,&OpndDesc::Reg32IS,&OpndDesc::Imm5,&OpndDesc::Imm5},ISMOVE,kLtAluShift,"bfi","0,1,2,3",1,kBitfield,0x33000000) +DEFINE_MOP(MOP_wbfirri5i5, {&OpndDesc::Reg32IDS,&OpndDesc::Reg32IS,&OpndDesc::Imm5,&OpndDesc::Imm5},ISMOVE,kLtAluShift,"bfi","0,1,2,3",1,MOP_wbfirri5i5Valid,kBitfield,0x33000000) /* MOP_xbfirri6i6 */ -DEFINE_MOP(MOP_xbfirri6i6, {&OpndDesc::Reg64IDS,&OpndDesc::Reg64IS,&OpndDesc::Imm6,&OpndDesc::Imm6},ISMOVE,kLtAluShift,"bfi","0,1,2,3",1,kBitfield,0xb3400000) +DEFINE_MOP(MOP_xbfirri6i6, {&OpndDesc::Reg64IDS,&OpndDesc::Reg64IS,&OpndDesc::Imm6,&OpndDesc::Imm6},ISMOVE,kLtAluShift,"bfi","0,1,2,3",1,MOP_xbfirri6i6Valid,kBitfield,0xb3400000) /* MOP_xlslrri6,--- Logical Shift Left */ -DEFINE_MOP(MOP_xlslrri6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6},0,kLtAluShift,"lsl","0,1,2",1,kBitfield,0xd3400000) +DEFINE_MOP(MOP_xlslrri6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6},0,kLtAluShift,"lsl","0,1,2",1,MOP_xlslrri6Valid,kBitfield,0xd3400000) /* MOP_wlslrri5 */ -DEFINE_MOP(MOP_wlslrri5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm8},0,kLtAluShift,"lsl","0,1,2",1,kBitfield,0x53000000) +DEFINE_MOP(MOP_wlslrri5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm8},0,kLtAluShift,"lsl","0,1,2",1,MOP_wlslrri5Valid,kBitfield,0x53000000) /* MOP_xasrrri6, */ -DEFINE_MOP(MOP_xasrrri6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6},0,kLtAluShift,"asr","0,1,2",1,kBitfield,0x9340fc00) +DEFINE_MOP(MOP_xasrrri6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6},0,kLtAluShift,"asr","0,1,2",1,MOP_xasrrri6Valid,kBitfield,0x9340fc00) /* MOP_wasrrri5 */ -DEFINE_MOP(MOP_wasrrri5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm8},0,kLtAluShift,"asr","0,1,2",1,kBitfield,0x13007c00) +DEFINE_MOP(MOP_wasrrri5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm8},0,kLtAluShift,"asr","0,1,2",1,MOP_wasrrri5Valid,kBitfield,0x13007c00) /* MOP_xlsrrri6, */ -DEFINE_MOP(MOP_xlsrrri6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6},0,kLtAluShift,"lsr","0,1,2",1,kBitfield,0xd340fc00) +DEFINE_MOP(MOP_xlsrrri6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Imm6},0,kLtAluShift,"lsr","0,1,2",1,MOP_xlsrrri6Valid,kBitfield,0xd340fc00) /* MOP_wlsrrri5 */ -DEFINE_MOP(MOP_wlsrrri5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm8},0,kLtAluShift,"lsr","0,1,2",1,kBitfield,0x53007c00) +DEFINE_MOP(MOP_wlsrrri5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Imm8},0,kLtAluShift,"lsr","0,1,2",1,MOP_wlsrrri5Valid,kBitfield,0x53007c00) /* MOP_xlslrrr, */ DEFINE_MOP(MOP_xlslrrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS},0,kLtAluShiftReg,"lsl","0,1,2",1,kDataProcess2Src,0x9ac02000) /* MOP_wlslrrr */ @@ -387,17 +393,17 @@ DEFINE_MOP(MOP_xrorrrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64I /* MOP_wrorrrr */ DEFINE_MOP(MOP_wrorrrr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS},0,kLtAluShiftReg,"ror","0,1,2",1, kDataProcess2Src, 0x1ac02c00) /* MOP_wtstri32 */ -DEFINE_MOP(MOP_wtstri32, {&OpndDesc::CCD,&OpndDesc::Reg32ID,&OpndDesc::Imm32},0,kLtAlu,"tst","1,2",1, kLogicalImm, 0x7200001f) +DEFINE_MOP(MOP_wtstri32, {&OpndDesc::CCD,&OpndDesc::Reg32ID,&OpndDesc::Imm32},0,kLtAlu,"tst","1,2",1,MOP_wtstri32Valid,kLogicalImm, 0x7200001f) /* MOP_xtstri64 */ -DEFINE_MOP(MOP_xtstri64, {&OpndDesc::CCD,&OpndDesc::Reg64ID,&OpndDesc::Imm64},0,kLtAlu,"tst","1,2",1, kLogicalImm, 0xf200001f) +DEFINE_MOP(MOP_xtstri64, {&OpndDesc::CCD,&OpndDesc::Reg64ID,&OpndDesc::Imm64},0,kLtAlu,"tst","1,2",1,MOP_xtstri64Valid,kLogicalImm, 0xf200001f) /* MOP_wtstrr */ DEFINE_MOP(MOP_wtstrr, {&OpndDesc::CCD,&OpndDesc::Reg32ID,&OpndDesc::Reg32IS},0,kLtAlu,"tst","1,2",1, kLogicalReg, 0x6a00001f) /* MOP_xtstrr */ DEFINE_MOP(MOP_xtstrr, {&OpndDesc::CCD,&OpndDesc::Reg64ID,&OpndDesc::Reg64IS},0,kLtAlu,"tst","1,2",1, kLogicalReg, 0xea00001f) /* MOP_wextrrrri5 -- Extracts a register from a pair of registers */ -DEFINE_MOP(MOP_wextrrrri5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Imm5},0,kLtAluShift,"extr","0,1,2,3",1, kExtract, 0x13800000) +DEFINE_MOP(MOP_wextrrrri5, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Imm5},0,kLtAluShift,"extr","0,1,2,3",1,MOP_wextrrrri5Valid,kExtract, 0x13800000) /* MOP_xextrrrri6 */ -DEFINE_MOP(MOP_xextrrrri6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Imm6},0,kLtAluShift,"extr","0,1,2,3",1, kExtract, 0x93c00000) +DEFINE_MOP(MOP_xextrrrri6, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Imm6},0,kLtAluShift,"extr","0,1,2,3",1,MOP_xextrrrri6Valid,kExtract, 0x93c00000) /* MOP_wsfmovri imm8->s */ DEFINE_MOP(MOP_wsfmovri, {&OpndDesc::Reg32FD,&OpndDesc::Imm8},ISMOVE,kLtFconst,"fmov","0,1",1,kFloatImm,0x1e201000) @@ -418,11 +424,11 @@ DEFINE_MOP(MOP_dabsrr, {&OpndDesc::Reg64FD,&OpndDesc::Reg64FS},0,kLtFpalu,"fabs" /* MOP_winegrr */ DEFINE_MOP(MOP_winegrr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS},0,kLtAlu,"neg","0,1",1,kAddSubReg,0x4b0003e0) /* MOP_winegrre */ -DEFINE_MOP(MOP_winegrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAlu,"neg","0,1,2",1, kAddSubShiftReg, 0x4b0003e0) +DEFINE_MOP(MOP_winegrrs, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAlu,"neg","0,1,2",1,MOP_winegrrsValid,kAddSubShiftReg, 0x4b0003e0) /* neg MOP_xinegrr */ DEFINE_MOP(MOP_xinegrr, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS},0,kLtAlu,"neg","0,1",1,kAddSubReg,0xcb0003e0) /* neg MOP_xinegrrs */ -DEFINE_MOP(MOP_xinegrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAlu,"neg","0,1,2",1, kAddSubShiftReg, 0xcb0003e0) +DEFINE_MOP(MOP_xinegrrs, {&OpndDesc::Reg64ID,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAlu,"neg","0,1,2",1,MOP_xinegrrsValid,kAddSubShiftReg, 0xcb0003e0) /* neg f32 */ DEFINE_MOP(MOP_wfnegrr, {&OpndDesc::Reg32FD,&OpndDesc::Reg32FS},0,kLtFpalu,"fneg","0,1",1,kFloatDataProcessing1,0x1e214000) /* neg f64 */ @@ -434,14 +440,14 @@ DEFINE_MOP(MOP_sdivrrr, {&OpndDesc::Reg32FD,&OpndDesc::Reg32FS,&OpndDesc::Reg32F DEFINE_MOP(MOP_ddivrrr, {&OpndDesc::Reg64FD,&OpndDesc::Reg64FS,&OpndDesc::Reg64FS},CANTHROW,kLtAdvsimdDivD,"fdiv","0,1,2",1,kFloatDataProcessing2,0x1e601800) /* MOP_smadd */ -DEFINE_MOP(MOP_smadd, {&OpndDesc::Reg32FD,&OpndDesc::Reg32FS,&OpndDesc::Reg32FS,&OpndDesc::Reg32FS},CANTHROW,kLtFpmul,"fmadd","0,1,2,3",1, kFloatDataProcessing3, 0x1f000000) +DEFINE_MOP(MOP_smadd, {&OpndDesc::Reg32FD,&OpndDesc::Reg32FS,&OpndDesc::Reg32FS,&OpndDesc::Reg32FS},CANTHROW,kLtFpmac,"fmadd","0,1,2,3",1, kFloatDataProcessing3, 0x1f000000) /* MOP_dmadd */ -DEFINE_MOP(MOP_dmadd, {&OpndDesc::Reg64FD,&OpndDesc::Reg64FS,&OpndDesc::Reg64FS,&OpndDesc::Reg64FS},CANTHROW,kLtFpmul,"fmadd","0,1,2,3",1, kFloatDataProcessing3, 0x1f400000) +DEFINE_MOP(MOP_dmadd, {&OpndDesc::Reg64FD,&OpndDesc::Reg64FS,&OpndDesc::Reg64FS,&OpndDesc::Reg64FS},CANTHROW,kLtFpmac,"fmadd","0,1,2,3",1, kFloatDataProcessing3, 0x1f400000) /* MOP_smsub */ -DEFINE_MOP(MOP_smsub, {&OpndDesc::Reg32FD,&OpndDesc::Reg32FS,&OpndDesc::Reg32FS,&OpndDesc::Reg32FS},CANTHROW,kLtFpmul,"fmsub","0,1,2,3",1, kFloatDataProcessing3, 0x1f008000) +DEFINE_MOP(MOP_smsub, {&OpndDesc::Reg32FD,&OpndDesc::Reg32FS,&OpndDesc::Reg32FS,&OpndDesc::Reg32FS},CANTHROW,kLtFpmac,"fmsub","0,1,2,3",1, kFloatDataProcessing3, 0x1f008000) /* MOP_dmsub */ -DEFINE_MOP(MOP_dmsub, {&OpndDesc::Reg64FD,&OpndDesc::Reg64FS,&OpndDesc::Reg64FS,&OpndDesc::Reg64FS},CANTHROW,kLtFpmul,"fmsub","0,1,2,3",1, kFloatDataProcessing3, 0x1f408000) +DEFINE_MOP(MOP_dmsub, {&OpndDesc::Reg64FD,&OpndDesc::Reg64FS,&OpndDesc::Reg64FS,&OpndDesc::Reg64FS},CANTHROW,kLtFpmac,"fmsub","0,1,2,3",1, kFloatDataProcessing3, 0x1f408000) /* MOP_snmul */ DEFINE_MOP(MOP_snmul, {&OpndDesc::Reg32FD,&OpndDesc::Reg32FS,&OpndDesc::Reg32FS},CANTHROW,kLtFpmul,"fnmul","0,1,2",1, kFloatDataProcessing2, 0x1e208800) @@ -524,86 +530,86 @@ DEFINE_MOP(MOP_sync_lock_test_setL, {&OpndDesc::Reg64ID,&OpndDesc::Reg32ID,&Opnd /* AARCH64 LOADS */ /* MOP_wldrsb --- Load Register Signed Byte */ -DEFINE_MOP(MOP_wldrsb, {&OpndDesc::Reg32ID,&OpndDesc::Mem8S},ISLOAD|CANTHROW,kLtLoad1,"ldrsb","0,1",1,StrLdr8ImmValid,kLoadStoreReg,0x38c00000) +DEFINE_MOP(MOP_wldrsb, {&OpndDesc::Reg32ID,&OpndDesc::Mem8S},ISLOAD|CANTHROW,kLtLoad1,"ldrsb","0,1",1,MOP_wldrsbValid,MOP_wldrsbSplit,kLoadStoreReg,0x38c00000) /* MOP_xldrsb --- Load Register Signed Byte */ -DEFINE_MOP(MOP_xldrsb, {&OpndDesc::Reg64ID,&OpndDesc::Mem8S},ISLOAD|CANTHROW,kLtLoad1,"ldrsb","0,1",1,StrLdr8ImmValid, kLoadStoreReg, 0x38800000) +DEFINE_MOP(MOP_xldrsb, {&OpndDesc::Reg64ID,&OpndDesc::Mem8S},ISLOAD|CANTHROW,kLtLoad1,"ldrsb","0,1",1,MOP_xldrsbValid,MOP_xldrsbSplit,kLoadStoreReg,0x38800000) /* MOP_wldrb */ -DEFINE_MOP(MOP_wldrb, {&OpndDesc::Reg32ID,&OpndDesc::Mem8S},ISLOAD|CANTHROW,kLtLoad1,"ldrb","0,1",1,StrLdr8ImmValid,kLoadStoreReg,0x38400000) +DEFINE_MOP(MOP_wldrb, {&OpndDesc::Reg32ID,&OpndDesc::Mem8S},ISLOAD|CANTHROW,kLtLoad1,"ldrb","0,1",1,MOP_wldrbValid,MOP_wldrbSplit,kLoadStoreReg,0x38400000) /* MOP_wldrsh --- Load Register Signed Halfword */ -DEFINE_MOP(MOP_wldrsh, {&OpndDesc::Reg32ID,&OpndDesc::Mem16S},ISLOAD|CANTHROW,kLtLoad1,"ldrsh","0,1",1,StrLdr16ImmValid,kLoadStoreReg,0x78c00000) +DEFINE_MOP(MOP_wldrsh, {&OpndDesc::Reg32ID,&OpndDesc::Mem16S},ISLOAD|CANTHROW,kLtLoad1,"ldrsh","0,1",1,MOP_wldrshValid,MOP_wldrshSplit,kLoadStoreReg,0x78c00000) /* MOP_xldrsh --- Load Register Signed Halfword */ -DEFINE_MOP(MOP_xldrsh, {&OpndDesc::Reg64ID,&OpndDesc::Mem16S},ISLOAD|CANTHROW,kLtLoad1,"ldrsh","0,1",1,StrLdr16ImmValid, kLoadStoreReg,0x7880000) +DEFINE_MOP(MOP_xldrsh, {&OpndDesc::Reg64ID,&OpndDesc::Mem16S},ISLOAD|CANTHROW,kLtLoad1,"ldrsh","0,1",1,MOP_xldrshValid,MOP_xldrshSplit, kLoadStoreReg,0x7880000) /* MOP_xldrsw --- Load Register Signed Word */ -DEFINE_MOP(MOP_xldrsw, {&OpndDesc::Reg64ID,&OpndDesc::Mem32S},ISLOAD|CANTHROW,kLtLoad1,"ldrsw","0,1",1,StrLdr32ImmValid) +DEFINE_MOP(MOP_xldrsw, {&OpndDesc::Reg64ID,&OpndDesc::Mem32S},ISLOAD|CANTHROW,kLtLoad1,"ldrsw","0,1",1,MOP_xldrswValid,MOP_xldrswSplit) /* MOP_wldrh */ -DEFINE_MOP(MOP_wldrh, {&OpndDesc::Reg32ID, &OpndDesc::Mem16S},ISLOAD|CANTHROW,kLtLoad1,"ldrh","0,1",1,StrLdr16ImmValid,kLoadStoreReg,0x78400000) +DEFINE_MOP(MOP_wldrh, {&OpndDesc::Reg32ID, &OpndDesc::Mem16S},ISLOAD|CANTHROW,kLtLoad1,"ldrh","0,1",1,MOP_wldrhValid,MOP_wldrhSplit,kLoadStoreReg,0x78400000) /* MOP_wldr */ -DEFINE_MOP(MOP_wldr, {&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|CANTHROW,kLtLoad1,"ldr","0,1",1,StrLdr32ImmValid,kLoadStoreReg,0xb8400000) +DEFINE_MOP(MOP_wldr, {&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|CANTHROW,kLtLoad1,"ldr","0,1",1,MOP_wldrValid,MOP_wldrSplit,kLoadStoreReg,0xb8400000) /* MOP_xldr */ -DEFINE_MOP(MOP_xldr, {&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|CANTHROW,kLtLoad2,"ldr","0,1",1,StrLdr64ImmValid,kLoadStoreReg,0xf8400000) +DEFINE_MOP(MOP_xldr, {&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|CANTHROW,kLtLoad2,"ldr","0,1",1,MOP_xldrValid,MOP_xldrSplit,kLoadStoreReg,0xf8400000) /* MOP_bldr */ -DEFINE_MOP(MOP_bldr, {&OpndDesc::Reg8FD,&OpndDesc::Mem8S},ISLOAD|CANTHROW,kLtFLoad64,"ldr","0,1",1,StrLdr8ImmValid,kLoadStoreFloat,0x3c400000) +DEFINE_MOP(MOP_bldr, {&OpndDesc::Reg8FD,&OpndDesc::Mem8S},ISLOAD|CANTHROW,kLtFLoad64,"ldr","0,1",1,MOP_bldrValid,MOP_bldrSplit,kLoadStoreFloat,0x3c400000) /* MOP_hldr */ -DEFINE_MOP(MOP_hldr, {&OpndDesc::Reg16FD,&OpndDesc::Mem16S},ISLOAD|CANTHROW,kLtFLoad64,"ldr","0,1",1,StrLdr16ImmValid,kLoadStoreFloat,0x7c400000) +DEFINE_MOP(MOP_hldr, {&OpndDesc::Reg16FD,&OpndDesc::Mem16S},ISLOAD|CANTHROW,kLtFLoad64,"ldr","0,1",1,MOP_hldrValid,MOP_hldrSplit,kLoadStoreFloat,0x7c400000) /* MOP_sldr */ -DEFINE_MOP(MOP_sldr, {&OpndDesc::Reg32FD,&OpndDesc::Mem32S},ISLOAD|CANTHROW,kLtFLoadMany,"ldr","0,1",1,StrLdr32ImmValid,kLoadStoreFloat,0xbc400000) +DEFINE_MOP(MOP_sldr, {&OpndDesc::Reg32FD,&OpndDesc::Mem32S},ISLOAD|CANTHROW,kLtFLoadMany,"ldr","0,1",1,MOP_sldrValid,MOP_sldrSplit,kLoadStoreFloat,0xbc400000) /* MOP_dldr */ -DEFINE_MOP(MOP_dldr, {&OpndDesc::Reg64FD,&OpndDesc::Mem64S},ISLOAD|CANTHROW,kLtFLoadMany,"ldr","0,1",1,StrLdr64ImmValid,kLoadStoreFloat,0xfc400000) +DEFINE_MOP(MOP_dldr, {&OpndDesc::Reg64FD,&OpndDesc::Mem64S},ISLOAD|CANTHROW,kLtFLoadMany,"ldr","0,1",1,MOP_dldrValid,MOP_dldrSplit,kLoadStoreFloat,0xfc400000) /* MOP_qldr */ -DEFINE_MOP(MOP_qldr, {&OpndDesc::Reg128VD,&OpndDesc::Mem128S},ISLOAD|CANTHROW,kLtFLoadMany,"ldr","0,1",1,StrLdr128ImmValid, kLoadStoreFloat, 0x3cc00000) +DEFINE_MOP(MOP_qldr, {&OpndDesc::Reg128VD,&OpndDesc::Mem128S},ISLOAD|CANTHROW,kLtFLoadMany,"ldr","0,1",1,MOP_qldrValid,MOP_qldrSplit, kLoadStoreFloat, 0x3cc00000) /* AArch64 LDP/LDPSW */ /* MOP_wldp */ -DEFINE_MOP(MOP_wldp, {&OpndDesc::Reg32ID,&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|ISLOADPAIR|CANTHROW,kLtLoad2,"ldp","0,1,2",1,StrLdr32PairImmValid,kLoadPair,0x28000000) +DEFINE_MOP(MOP_wldp, {&OpndDesc::Reg32ID,&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|ISLOADPAIR|CANTHROW,kLtLoad2,"ldp","0,1,2",1,MOP_wldpValid,MOP_wldpSplit,kLoadPair,0x28000000) /* MOP_xldp */ -DEFINE_MOP(MOP_xldp, {&OpndDesc::Reg64ID,&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|ISLOADPAIR|CANTHROW,kLtLoad3plus,"ldp","0,1,2",1,StrLdr64PairImmValid,kLoadPair,0xa8000000) +DEFINE_MOP(MOP_xldp, {&OpndDesc::Reg64ID,&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|ISLOADPAIR|CANTHROW,kLtLoad3plus,"ldp","0,1,2",1,MOP_xldpValid,MOP_xldpSplit,kLoadPair,0xa8000000) /* MOP_xldpsw */ -DEFINE_MOP(MOP_xldpsw, {&OpndDesc::Reg64ID,&OpndDesc::Reg64ID,&OpndDesc::Mem32S},ISLOAD|ISLOADPAIR|CANTHROW,kLtLoad2,"ldpsw","0,1,2",1,StrLdr32PairImmValid,kLoadPair,0x68400000) +DEFINE_MOP(MOP_xldpsw, {&OpndDesc::Reg64ID,&OpndDesc::Reg64ID,&OpndDesc::Mem32S},ISLOAD|ISLOADPAIR|CANTHROW,kLtLoad2,"ldpsw","0,1,2",1,MOP_xldpswValid,MOP_xldpswSplit,kLoadPair,0x68400000) /* MOP_sldp */ -DEFINE_MOP(MOP_sldp, {&OpndDesc::Reg32FD,&OpndDesc::Reg32FD,&OpndDesc::Mem32S},ISLOAD|ISLOADPAIR|CANTHROW,kLtFLoad64,"ldp","0,1,2",1,StrLdr32PairImmValid,kLoadPairFloat,0x2c000000) +DEFINE_MOP(MOP_sldp, {&OpndDesc::Reg32FD,&OpndDesc::Reg32FD,&OpndDesc::Mem32S},ISLOAD|ISLOADPAIR|CANTHROW,kLtFLoad64,"ldp","0,1,2",1,MOP_sldpValid,MOP_sldpSplit,kLoadPairFloat,0x2c000000) /* MOP_dldp */ -DEFINE_MOP(MOP_dldp, {&OpndDesc::Reg64FD,&OpndDesc::Reg64FD,&OpndDesc::Mem64S},ISLOAD|ISLOADPAIR|CANTHROW,kLtFLoadMany,"ldp","0,1,2",1,StrLdr64PairImmValid,kLoadPairFloat,0x6c000000) +DEFINE_MOP(MOP_dldp, {&OpndDesc::Reg64FD,&OpndDesc::Reg64FD,&OpndDesc::Mem64S},ISLOAD|ISLOADPAIR|CANTHROW,kLtFLoadMany,"ldp","0,1,2",1,MOP_dldpValid,MOP_dldpSplit,kLoadPairFloat,0x6c000000) /* MOP_qldp */ -DEFINE_MOP(MOP_qldp, {&OpndDesc::Reg128VD,&OpndDesc::Reg128VD,&OpndDesc::Mem128S},ISLOAD|ISLOADPAIR|CANTHROW,kLtFLoadMany,"ldp","0,1,2",1,StrLdr128PairImmValid, kLoadPairFloat, 0xac000000) +DEFINE_MOP(MOP_qldp, {&OpndDesc::Reg128VD,&OpndDesc::Reg128VD,&OpndDesc::Mem128S},ISLOAD|ISLOADPAIR|CANTHROW,kLtFLoadMany,"ldp","0,1,2",1,MOP_qldpValid,MOP_qldpSplit, kLoadPairFloat, 0xac000000) /* AARCH64 Load with Acquire semantics */ /* MOP_wldarb */ -DEFINE_MOP(MOP_wldarb, {&OpndDesc::Reg32ID,&OpndDesc::Mem8S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldarb","0,1",1,StrLdr8ImmValid,kLoadStoreAR,0x8dffc00) +DEFINE_MOP(MOP_wldarb, {&OpndDesc::Reg32ID,&OpndDesc::Mem8S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldarb","0,1",1,MOP_wldarbValid,kLoadStoreAR,0x8dffc00) /* MOP_wldarh */ -DEFINE_MOP(MOP_wldarh, {&OpndDesc::Reg32ID, &OpndDesc::Mem16S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldarh","0,1",1,StrLdr16ImmValid,kLoadStoreAR,0x48dffc00) +DEFINE_MOP(MOP_wldarh, {&OpndDesc::Reg32ID, &OpndDesc::Mem16S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldarh","0,1",1,MOP_wldarhValid,kLoadStoreAR,0x48dffc00) /* MOP_wldar */ -DEFINE_MOP(MOP_wldar, {&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldar","0,1",1,StrLdr32ImmValid,kLoadStoreAR,0x88dffc00) +DEFINE_MOP(MOP_wldar, {&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldar","0,1",1,MOP_wldarValid,kLoadStoreAR,0x88dffc00) /* MOP_xldar */ -DEFINE_MOP(MOP_xldar, {&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldar","0,1",1,StrLdr64ImmValid,kLoadStoreAR,0xc8dffc00) +DEFINE_MOP(MOP_xldar, {&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldar","0,1",1,MOP_xldarValid,kLoadStoreAR,0xc8dffc00) /* MOP_wmovkri16 */ -DEFINE_MOP(MOP_wmovkri16, {&OpndDesc::Reg32IDS,&OpndDesc::Imm16,&OpndDesc::Lsl4},ISMOVE,kLtShift,"movk","0,1,2",1,Imm16BitValid,kMoveWide,0x72800000) +DEFINE_MOP(MOP_wmovkri16, {&OpndDesc::Reg32IDS,&OpndDesc::Imm16,&OpndDesc::Lsl4},ISMOVE,kLtShift,"movk","0,1,2",1,MOP_wmovkri16Valid,kMoveWide,0x72800000) /* MOP_xmovkri16 */ -DEFINE_MOP(MOP_xmovkri16, {&OpndDesc::Reg64IDS,&OpndDesc::Imm16,&OpndDesc::Lsl6},ISMOVE,kLtShift,"movk","0,1,2",1,Imm16BitValid,kMoveWide,0xf2800000) +DEFINE_MOP(MOP_xmovkri16, {&OpndDesc::Reg64IDS,&OpndDesc::Imm16,&OpndDesc::Lsl6},ISMOVE,kLtShift,"movk","0,1,2",1,MOP_xmovkri16Valid,kMoveWide,0xf2800000) /* MOP_wmovzri16 */ -DEFINE_MOP(MOP_wmovzri16, {&OpndDesc::Reg32ID,&OpndDesc::Imm16,&OpndDesc::Lsl4},ISMOVE,kLtShift,"movz","0,1,2",1,Imm16BitValid,kMoveWide,0x52800000) +DEFINE_MOP(MOP_wmovzri16, {&OpndDesc::Reg32ID,&OpndDesc::Imm16,&OpndDesc::Lsl4},ISMOVE,kLtShift,"movz","0,1,2",1,MOP_wmovzri16Valid,kMoveWide,0x52800000) /* MOP_xmovzri16 */ -DEFINE_MOP(MOP_xmovzri16, {&OpndDesc::Reg64ID,&OpndDesc::Imm16,&OpndDesc::Lsl6},ISMOVE,kLtShift,"movz","0,1,2",1,Imm16BitValid,kMoveWide,0xd2800000) +DEFINE_MOP(MOP_xmovzri16, {&OpndDesc::Reg64ID,&OpndDesc::Imm16,&OpndDesc::Lsl6},ISMOVE,kLtShift,"movz","0,1,2",1,MOP_xmovzri16Valid,kMoveWide,0xd2800000) /* MOP_wmovnri16 */ -DEFINE_MOP(MOP_wmovnri16, {&OpndDesc::Reg32ID,&OpndDesc::Imm16,&OpndDesc::Lsl4},ISMOVE,kLtShift,"movn","0,1,2",1,Imm16BitValid,kMoveWide,0x12800000) +DEFINE_MOP(MOP_wmovnri16, {&OpndDesc::Reg32ID,&OpndDesc::Imm16,&OpndDesc::Lsl4},ISMOVE,kLtShift,"movn","0,1,2",1,MOP_wmovnri16Valid,kMoveWide,0x12800000) /* MOP_xmovnri16 */ -DEFINE_MOP(MOP_xmovnri16, {&OpndDesc::Reg64ID,&OpndDesc::Imm16,&OpndDesc::Lsl6},ISMOVE,kLtShift,"movn","0,1,2",1,Imm16BitValid,kMoveWide,0x92800000) +DEFINE_MOP(MOP_xmovnri16, {&OpndDesc::Reg64ID,&OpndDesc::Imm16,&OpndDesc::Lsl6},ISMOVE,kLtShift,"movn","0,1,2",1,MOP_xmovnri16Valid,kMoveWide,0x92800000) /* AARCH64 Load exclusive with/without acquire semantics */ -DEFINE_MOP(MOP_wldxrb, {&OpndDesc::Reg32ID,&OpndDesc::Mem8S},ISLOAD|ISATOMIC|CANTHROW,kLtLoad1,"ldxrb","0,1",1,StrLdr8ImmValid,kLoadExclusive,0x85f7c00) -DEFINE_MOP(MOP_wldxrh, {&OpndDesc::Reg32ID,&OpndDesc::Mem16S},ISLOAD|ISATOMIC|CANTHROW,kLtLoad1,"ldxrh","0,1",1,StrLdr16ImmValid,kLoadExclusive,0x485f7c00) -DEFINE_MOP(MOP_wldxr, {&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|ISATOMIC|CANTHROW,kLtLoad1,"ldxr","0,1",1,StrLdr32ImmValid,kLoadExclusive,0x885f7c00) -DEFINE_MOP(MOP_xldxr, {&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|ISATOMIC|CANTHROW,kLtLoad1,"ldxr","0,1",1,StrLdr64ImmValid,kLoadExclusive,0xc85f7c00) +DEFINE_MOP(MOP_wldxrb, {&OpndDesc::Reg32ID,&OpndDesc::Mem8S},ISLOAD|ISATOMIC|CANTHROW,kLtLoad1,"ldxrb","0,1",1,MOP_wldxrbValid,kLoadExclusive,0x85f7c00) +DEFINE_MOP(MOP_wldxrh, {&OpndDesc::Reg32ID,&OpndDesc::Mem16S},ISLOAD|ISATOMIC|CANTHROW,kLtLoad1,"ldxrh","0,1",1,MOP_wldxrhValid,kLoadExclusive,0x485f7c00) +DEFINE_MOP(MOP_wldxr, {&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|ISATOMIC|CANTHROW,kLtLoad1,"ldxr","0,1",1,MOP_wldxrValid,kLoadExclusive,0x885f7c00) +DEFINE_MOP(MOP_xldxr, {&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|ISATOMIC|CANTHROW,kLtLoad1,"ldxr","0,1",1,MOP_xldxrValid,kLoadExclusive,0xc85f7c00) -DEFINE_MOP(MOP_wldaxrb,{&OpndDesc::Reg32ID,&OpndDesc::Mem8S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxrb","0,1",1,StrLdr8ImmValid,kLoadExclusive,0x85ffc00) -DEFINE_MOP(MOP_wldaxrh,{&OpndDesc::Reg32ID,&OpndDesc::Mem16S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxrh","0,1",1,StrLdr16ImmValid,kLoadExclusive,0x485ffc00) -DEFINE_MOP(MOP_wldaxr, {&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxr","0,1",1,StrLdr32ImmValid,kLoadExclusive,0x885ffc00) -DEFINE_MOP(MOP_xldaxr, {&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxr","0,1",1,StrLdr64ImmValid,kLoadExclusive,0xc85ffc00) +DEFINE_MOP(MOP_wldaxrb,{&OpndDesc::Reg32ID,&OpndDesc::Mem8S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxrb","0,1",1,MOP_wldaxrbValid,kLoadExclusive,0x85ffc00) +DEFINE_MOP(MOP_wldaxrh,{&OpndDesc::Reg32ID,&OpndDesc::Mem16S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxrh","0,1",1,MOP_wldaxrhValid,kLoadExclusive,0x485ffc00) +DEFINE_MOP(MOP_wldaxr, {&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxr","0,1",1,MOP_wldaxrValid,kLoadExclusive,0x885ffc00) +DEFINE_MOP(MOP_xldaxr, {&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxr","0,1",1,MOP_xldaxrValid,kLoadExclusive,0xc85ffc00) -DEFINE_MOP(MOP_wldaxp, {&OpndDesc::Reg32ID,&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|ISLOADPAIR|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxp","0,1,2",1,StrLdr32ImmValid,kLoadExclusivePair,0x887f8000) -DEFINE_MOP(MOP_xldaxp, {&OpndDesc::Reg64ID,&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|ISLOADPAIR|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxp","0,1,2",1,StrLdr64ImmValid,kLoadExclusivePair,0xc87f8000) +DEFINE_MOP(MOP_wldaxp, {&OpndDesc::Reg32ID,&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|ISLOADPAIR|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxp","0,1,2",1,MOP_wldaxpValid,kLoadExclusivePair,0x887f8000) +DEFINE_MOP(MOP_xldaxp, {&OpndDesc::Reg64ID,&OpndDesc::Reg64ID,&OpndDesc::Mem64S},ISLOAD|ISLOADPAIR|ISATOMIC|HASACQUIRE|CANTHROW,kLtLoad1,"ldaxp","0,1,2",1,MOP_xldaxpValid,kLoadExclusivePair,0xc87f8000) /* MOP_vsqrts */ DEFINE_MOP(MOP_vsqrts, {&OpndDesc::Reg32FD,&OpndDesc::Reg32FS},CANTHROW,kLtAdvsimdDivS,"fsqrt","0,1",1,kFloatDataProcessing1,0x1e21c000) @@ -683,47 +689,47 @@ DEFINE_MOP(MOP_dcmpqrr, {&OpndDesc::CCD, &OpndDesc::Reg64FS,&OpndDesc::Reg64FS}, /* AARCH64 Integer COMPARES */ /* MOP_wcmpri -- AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_wcmpri, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"cmp","1,2",1,Imm12BitValid,kAddSubImm,0x7100001f) +DEFINE_MOP(MOP_wcmpri, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"cmp","1,2",1,MOP_wcmpriValid,kAddSubImm,0x7100001f) /* MOP_wcmprr -- register, shifted register, AArch64 cmp has no dest operand */ DEFINE_MOP(MOP_wcmprr, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS},0,kLtAlu,"cmp","1,2",1,kAddSubReg,0x6b00001f) /* MOP_wcmprrs -- register, shifted register, AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_wcmprrs, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAlu,"cmp","1,2,3",1, kAddSubShiftReg, 0x6b00001f) +DEFINE_MOP(MOP_wcmprrs, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAlu,"cmp","1,2,3",1,MOP_wcmprrsValid,kAddSubShiftReg, 0x6b00001f) /* MOP_wwcmprre -- register, shifted register, AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_wwcmprre, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAlu,"cmp","1,2,3",1, kAddSubExtendReg, 0x6b20001f) +DEFINE_MOP(MOP_wwcmprre, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAlu,"cmp","1,2,3",1,MOP_wwcmprreValid,kAddSubExtendReg, 0x6b20001f) /* MOP_xcmpri -- AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_xcmpri, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Imm16},0,kLtAlu,"cmp","1,2",1,Imm16BitValid,kAddSubImm,0xf100001f) +DEFINE_MOP(MOP_xcmpri, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Imm16},0,kLtAlu,"cmp","1,2",1,MOP_xcmpriValid,kAddSubImm,0xf100001f) /* MOP_xcmprr -- register, shifted register, AArch64 cmp has no dest operand */ DEFINE_MOP(MOP_xcmprr, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg64IS},0,kLtAlu,"cmp","1,2",1,kAddSubReg,0xeb00001f) /* MOP_xcmprrs -- register, shifted register, AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_xcmprrs, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAlu,"cmp","1,2,3",1, kAddSubShiftReg, 0xeb00001f) +DEFINE_MOP(MOP_xcmprrs, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAlu,"cmp","1,2,3",1,MOP_xcmprrsValid,kAddSubShiftReg, 0xeb00001f) /* MOP_xwcmprre -- register, shifted register, AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_xwcmprre, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAlu,"cmp","1,2,3",1, kAddSubExtendReg, 0xeb20001f) +DEFINE_MOP(MOP_xwcmprre, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAlu,"cmp","1,2,3",1,MOP_xwcmprreValid,kAddSubExtendReg, 0xeb20001f) /* MOP_wccmpriic -- AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_wccmpriic, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Imm5,&OpndDesc::Imm4,&OpndDesc::Cond,&OpndDesc::CCS},0,kLtAlu,"ccmp","1,2,3,4",1,kCondCompareImm,0x7a400800) +DEFINE_MOP(MOP_wccmpriic, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Imm5,&OpndDesc::Imm4,&OpndDesc::Cond,&OpndDesc::CCS},0,kLtAlu,"ccmp","1,2,3,4",1,MOP_wccmpriicValid,MOP_wccmpriicSplit,kCondCompareImm,0x7a400800) /* MOP_wccmprric -- register, shifted register, AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_wccmprric, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Imm4,&OpndDesc::Cond,&OpndDesc::CCS},0,kLtAlu,"ccmp","1,2,3,4",1,kCondCompareReg,0x7a400000) +DEFINE_MOP(MOP_wccmprric, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Imm4,&OpndDesc::Cond,&OpndDesc::CCS},0,kLtAlu,"ccmp","1,2,3,4",1,MOP_wccmprricValid,kCondCompareReg,0x7a400000) /* MOP_xccmpriic -- AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_xccmpriic, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Imm5,&OpndDesc::Imm4,&OpndDesc::Cond,&OpndDesc::CCS},0,kLtAlu,"ccmp","1,2,3,4",1,kCondCompareImm,0xfa400800) +DEFINE_MOP(MOP_xccmpriic, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Imm5,&OpndDesc::Imm4,&OpndDesc::Cond,&OpndDesc::CCS},0,kLtAlu,"ccmp","1,2,3,4",1,MOP_xccmpriicValid,MOP_xccmpriicSplit,kCondCompareImm,0xfa400800) /* MOP_xccmprric -- register, shifted register, AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_xccmprric, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Imm4,&OpndDesc::Cond,&OpndDesc::CCS},0,kLtAlu,"ccmp","1,2,3,4",1,kCondCompareReg,0xfa400000) +DEFINE_MOP(MOP_xccmprric, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Imm4,&OpndDesc::Cond,&OpndDesc::CCS},0,kLtAlu,"ccmp","1,2,3,4",1,MOP_xccmprricValid,kCondCompareReg,0xfa400000) /* MOP_wcmnri -- AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_wcmnri, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"cmn","1,2",1,Imm12BitValid,kAddSubImm,0x3100001f) +DEFINE_MOP(MOP_wcmnri, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Imm12},0,kLtAlu,"cmn","1,2",1,MOP_wcmnriValid,kAddSubImm,0x3100001f) /* MOP_wcmnrr -- register, shifted register, AArch64 cmp has no dest operand */ DEFINE_MOP(MOP_wcmnrr, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS},0,kLtAlu,"cmn","1,2",1,kAddSubReg,0x2b00001f) /* MOP_wcmnrrs -- register, shifted register, AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_wcmnrrs, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAlu,"cmn","1,2,3",1, kAddSubShiftReg, 0x2b00001f) +DEFINE_MOP(MOP_wcmnrrs, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Bitshift32},0,kLtAlu,"cmn","1,2,3",1,MOP_wcmnrrsValid,kAddSubShiftReg, 0x2b00001f) /* MOP_wwcmnrre -- register, shifted register, AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_wwcmnrre, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAlu,"cmn","1,2,3",1, kAddSubExtendReg, 0x2b20001f) +DEFINE_MOP(MOP_wwcmnrre, {&OpndDesc::CCD, &OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAlu,"cmn","1,2,3",1,MOP_wwcmnrreValid,kAddSubExtendReg, 0x2b20001f) /* MOP_xcmnri -- AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_xcmnri, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Imm16},0,kLtAlu,"cmn","1,2",1,Imm16BitValid,kAddSubImm,0xb100001f) +DEFINE_MOP(MOP_xcmnri, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Imm16},0,kLtAlu,"cmn","1,2",1,MOP_xcmnriValid,kAddSubImm,0xb100001f) /* MOP_xcmnrr -- register, shifted register, AArch64 cmp has no dest operand */ DEFINE_MOP(MOP_xcmnrr, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg64IS},0,kLtAlu,"cmn","1,2",1,kAddSubReg,0xab00001f) /* MOP_xcmnrrs -- register, shifted register, AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_xcmnrrs, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAlu,"cmn","1,2,3",1, kAddSubShiftReg, 0xab00001f) +DEFINE_MOP(MOP_xcmnrrs, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Bitshift64},0,kLtAlu,"cmn","1,2,3",1,MOP_xcmnrrsValid,kAddSubShiftReg, 0xab00001f) /* MOP_xwcmnrre -- register, shifted register, AArch64 cmp has no dest operand */ -DEFINE_MOP(MOP_xwcmnrre, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAlu,"cmn","1,2,3",1, kAddSubExtendReg, 0xab20001f) +DEFINE_MOP(MOP_xwcmnrre, {&OpndDesc::CCD, &OpndDesc::Reg64IS,&OpndDesc::Reg32IS,&OpndDesc::Extendshift64},0,kLtAlu,"cmn","1,2,3",1,MOP_xwcmnrreValid,kAddSubExtendReg, 0xab20001f) /* AArch64 branches */ /* MOP_xbr -- branch to register */ @@ -741,67 +747,71 @@ DEFINE_MOP(MOP_wcbz, {&OpndDesc::Reg32IS,&OpndDesc::AddressName},ISCONDBRANCH,kL DEFINE_MOP(MOP_xcbz, {&OpndDesc::Reg64IS,&OpndDesc::AddressName},ISCONDBRANCH,kLtBranch,"cbz","0,1",1,kCompareBranch,0xb4000000) /* MOP_wtbnz --- Test bit and Branch if Nonzero */ -DEFINE_MOP(MOP_wtbnz, {&OpndDesc::Reg32IS,&OpndDesc::Imm8,&OpndDesc::AddressName},ISCONDBRANCH,kLtBranch,"tbnz","0,1,2",1,kTestBranch,0x37000000) +DEFINE_MOP(MOP_wtbnz, {&OpndDesc::Reg32IS,&OpndDesc::Imm8,&OpndDesc::AddressName},ISCONDBRANCH,kLtBranch,"tbnz","0,1,2",1,MOP_wtbnzValid,kTestBranch,0x37000000) /* MOP_xtbnz */ -DEFINE_MOP(MOP_xtbnz, {&OpndDesc::Reg64IS,&OpndDesc::Imm8,&OpndDesc::AddressName},ISCONDBRANCH,kLtBranch,"tbnz","0,1,2",1,kTestBranch,0xb7000000) +DEFINE_MOP(MOP_xtbnz, {&OpndDesc::Reg64IS,&OpndDesc::Imm8,&OpndDesc::AddressName},ISCONDBRANCH,kLtBranch,"tbnz","0,1,2",1,MOP_xtbnzValid,kTestBranch,0xb7000000) /* MOP_wtbz --- Test bit and Branch if Zero */ -DEFINE_MOP(MOP_wtbz, {&OpndDesc::Reg32IS,&OpndDesc::Imm8,&OpndDesc::AddressName},ISCONDBRANCH,kLtBranch,"tbz","0,1,2",1,kTestBranch,0x36000000) +DEFINE_MOP(MOP_wtbz, {&OpndDesc::Reg32IS,&OpndDesc::Imm8,&OpndDesc::AddressName},ISCONDBRANCH,kLtBranch,"tbz","0,1,2",1,MOP_wtbzValid,kTestBranch,0x36000000) /* MOP_xtbz */ -DEFINE_MOP(MOP_xtbz, {&OpndDesc::Reg64IS,&OpndDesc::Imm8,&OpndDesc::AddressName},ISCONDBRANCH,kLtBranch,"tbz","0,1,2",1,kTestBranch,0xb6000000) +DEFINE_MOP(MOP_xtbz, {&OpndDesc::Reg64IS,&OpndDesc::Imm8,&OpndDesc::AddressName},ISCONDBRANCH,kLtBranch,"tbz","0,1,2",1,MOP_xtbzValid,kTestBranch,0xb6000000) /* AARCH64 STORES */ /* MOP_wstrb -- Store Register Byte */ -DEFINE_MOP(MOP_wstrb, {&OpndDesc::Reg32IS,&OpndDesc::Mem8D},ISSTORE|CANTHROW,kLtStore1,"strb","0,1",1,StrLdr8ImmValid,kLoadStoreReg,0x38000000) +DEFINE_MOP(MOP_wstrb, {&OpndDesc::Reg32IS,&OpndDesc::Mem8D},ISSTORE|CANTHROW,kLtStore1,"strb","0,1",1,MOP_wstrbValid,MOP_wstrbSplit,kLoadStoreReg,0x38000000) /* MOP_wstrh -- Store Register Halfword */ -DEFINE_MOP(MOP_wstrh, {&OpndDesc::Reg32IS,&OpndDesc::Mem16D},ISSTORE|CANTHROW,kLtStore1,"strh","0,1",1,StrLdr16ImmValid,kLoadStoreReg,0x78000000) +DEFINE_MOP(MOP_wstrh, {&OpndDesc::Reg32IS,&OpndDesc::Mem16D},ISSTORE|CANTHROW,kLtStore1,"strh","0,1",1,MOP_wstrhValid,MOP_wstrhSplit,kLoadStoreReg,0x78000000) /* MOP_wstr -- Store Register Word */ -DEFINE_MOP(MOP_wstr, {&OpndDesc::Reg32IS,&OpndDesc::Mem32D},ISSTORE|CANTHROW,kLtStore1,"str","0,1",1,StrLdr32ImmValid,kLoadStoreReg,0xb8000000) +DEFINE_MOP(MOP_wstr, {&OpndDesc::Reg32IS,&OpndDesc::Mem32D},ISSTORE|CANTHROW,kLtStore1,"str","0,1",1,MOP_wstrValid,MOP_wstrSplit,kLoadStoreReg,0xb8000000) /* MOP_xstr -- Store Register Double word */ -DEFINE_MOP(MOP_xstr, {&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|CANTHROW,kLtStore2,"str","0,1",1,StrLdr64ImmValid,kLoadStoreReg,0xf8000000) +DEFINE_MOP(MOP_xstr, {&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|CANTHROW,kLtStore2,"str","0,1",1,MOP_xstrValid,MOP_xstrSplit,kLoadStoreReg,0xf8000000) /* MOP_sstr -- Store Register SIMD/FP Float */ -DEFINE_MOP(MOP_sstr, {&OpndDesc::Reg32FS,&OpndDesc::Mem32D},ISSTORE|CANTHROW,kLtStore2,"str","0,1",1,StrLdr32ImmValid,kLoadStoreFloat,0xbc000000) +DEFINE_MOP(MOP_sstr, {&OpndDesc::Reg32FS,&OpndDesc::Mem32D},ISSTORE|CANTHROW,kLtStore2,"str","0,1",1,MOP_sstrValid,MOP_sstrSplit,kLoadStoreFloat,0xbc000000) /* MOP_dstr -- Store Register SIMD/FP Double */ -DEFINE_MOP(MOP_dstr, {&OpndDesc::Reg64FS,&OpndDesc::Mem64D},ISSTORE|CANTHROW,kLtStore3plus,"str","0,1",1,StrLdr64ImmValid,kLoadStoreFloat,0xfc000000) +DEFINE_MOP(MOP_dstr, {&OpndDesc::Reg64FS,&OpndDesc::Mem64D},ISSTORE|CANTHROW,kLtStore3plus,"str","0,1",1,MOP_dstrValid,MOP_dstrSplit,kLoadStoreFloat,0xfc000000) /* MOP_qstr -- Store Register SIMD/FP Double */ -DEFINE_MOP(MOP_qstr, {&OpndDesc::Reg128VS,&OpndDesc::Mem128D},ISSTORE|CANTHROW,kLtStore3plus,"str","0,1",1,StrLdr128ImmValid, kLoadStoreFloat, 0x3c800000) +DEFINE_MOP(MOP_qstr, {&OpndDesc::Reg128VS,&OpndDesc::Mem128D},ISSTORE|CANTHROW,kLtStore3plus,"str","0,1",1,MOP_qstrValid,MOP_qstrSplit, kLoadStoreFloat, 0x3c800000) /* AArch64 STP. */ /* MOP_wstp */ -DEFINE_MOP(MOP_wstp, {&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Mem32D},ISSTORE|ISSTOREPAIR|CANTHROW,kLtStore2,"stp","0,1,2",1,StrLdr32PairImmValid,kStorePair,0x28000000) +DEFINE_MOP(MOP_wstp, {&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Mem32D},ISSTORE|ISSTOREPAIR|CANTHROW,kLtStore2,"stp","0,1,2",1,MOP_wstpValid,MOP_wstpSplit,kStorePair,0x28000000) /* MOP_xstp */ -DEFINE_MOP(MOP_xstp, {&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|ISSTOREPAIR|CANTHROW,kLtStore3plus,"stp","0,1,2",1,StrLdr64PairImmValid,kStorePair,0xa8000000) +DEFINE_MOP(MOP_xstp, {&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|ISSTOREPAIR|CANTHROW,kLtStore3plus,"stp","0,1,2",1,MOP_xstpValid,MOP_xstpSplit,kStorePair,0xa8000000) /* AArch64 does not define STPSW. It has no practical value. */ /* MOP_sstp */ -DEFINE_MOP(MOP_sstp, {&OpndDesc::Reg32FS,&OpndDesc::Reg32FS,&OpndDesc::Mem32D},ISSTORE|ISSTOREPAIR|CANTHROW,kLtAdvsimdMulQ,"stp","0,1,2",1,StrLdr32PairImmValid,kStorePairFloat,0x2c000000) +DEFINE_MOP(MOP_sstp, {&OpndDesc::Reg32FS,&OpndDesc::Reg32FS,&OpndDesc::Mem32D},ISSTORE|ISSTOREPAIR|CANTHROW,kLtAdvsimdMulQ,"stp","0,1,2",1,MOP_sstpValid,MOP_sstpSplit,kStorePairFloat,0x2c000000) /* MOP_dstp */ -DEFINE_MOP(MOP_dstp, {&OpndDesc::Reg64FS,&OpndDesc::Reg64FS,&OpndDesc::Mem64D},ISSTORE|ISSTOREPAIR|CANTHROW,kLtAdvsimdMulQ,"stp","0,1,2",1,StrLdr64PairImmValid,kStorePairFloat,0x6c000000) +DEFINE_MOP(MOP_dstp, {&OpndDesc::Reg64FS,&OpndDesc::Reg64FS,&OpndDesc::Mem64D},ISSTORE|ISSTOREPAIR|CANTHROW,kLtAdvsimdMulQ,"stp","0,1,2",1,MOP_dstpValid,MOP_dstpSplit,kStorePairFloat,0x6c000000) /* MOP_qstp */ -DEFINE_MOP(MOP_qstp, {&OpndDesc::Reg128VS,&OpndDesc::Reg128VS,&OpndDesc::Mem128D},ISSTORE|ISSTOREPAIR|CANTHROW,kLtAdvsimdMulQ,"stp","0,1,2",1,StrLdr128PairImmValid, kStorePairFloat, 0xac000000) +DEFINE_MOP(MOP_qstp, {&OpndDesc::Reg128VS,&OpndDesc::Reg128VS,&OpndDesc::Mem128D},ISSTORE|ISSTOREPAIR|CANTHROW,kLtAdvsimdMulQ,"stp","0,1,2",1,MOP_qstpValid,MOP_qstpSplit, kStorePairFloat, 0xac000000) /* AARCH64 Store with Release semantics */ /* MOP_wstlrb -- Store-Release Register Byte */ -DEFINE_MOP(MOP_wstlrb, {&OpndDesc::Reg32IS,&OpndDesc::Mem8D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlrb","0,1",1,StrLdr8ImmValid,kLoadStoreAR,0x89ffc00) +DEFINE_MOP(MOP_wstlrb, {&OpndDesc::Reg32IS,&OpndDesc::Mem8D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlrb","0,1",1,MOP_wstlrbValid,kLoadStoreAR,0x89ffc00) /* MOP_wstlrh -- Store-Release Register Halfword */ -DEFINE_MOP(MOP_wstlrh, {&OpndDesc::Reg32IS,&OpndDesc::Mem16D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlrh","0,1",1,StrLdr16ImmValid,kLoadStoreAR,0x489ffc00) +DEFINE_MOP(MOP_wstlrh, {&OpndDesc::Reg32IS,&OpndDesc::Mem16D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlrh","0,1",1,MOP_wstlrhValid,kLoadStoreAR,0x489ffc00) /* MOP_wstlr -- Store-Release Register Word */ -DEFINE_MOP(MOP_wstlr, {&OpndDesc::Reg32IS,&OpndDesc::Mem32D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlr","0,1",1,StrLdr32ImmValid,kLoadStoreAR,0x889ffc00) +DEFINE_MOP(MOP_wstlr, {&OpndDesc::Reg32IS,&OpndDesc::Mem32D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlr","0,1",1,MOP_wstlrValid,kLoadStoreAR,0x889ffc00) /* MOP_xstlr -- Store-Release Register Double word */ -DEFINE_MOP(MOP_xstlr, {&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlr","0,1",1,StrLdr64ImmValid,kLoadStoreAR,0xc89ffc00) +DEFINE_MOP(MOP_xstlr, {&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlr","0,1",1,MOP_xstlrValid,kLoadStoreAR,0xc89ffc00) /* AARCH64 Store exclusive with/without release semantics */ -DEFINE_MOP(MOP_wstxrb, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem8D},ISSTORE|ISATOMIC|CANTHROW,kLtStore1,"stxrb","0,1,2",1,StrLdr8ImmValid,kStoreExclusive,0x8007c00) -DEFINE_MOP(MOP_wstxrh, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem16D},ISSTORE|ISATOMIC|CANTHROW,kLtStore1,"stxrh","0,1,2",1,StrLdr16ImmValid,kStoreExclusive,0x48007c00) -DEFINE_MOP(MOP_wstxr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem32D},ISSTORE|ISATOMIC|CANTHROW,kLtStore1,"stxr","0,1,2",1,StrLdr32ImmValid,kStoreExclusive,0x88007c00) -DEFINE_MOP(MOP_xstxr, {&OpndDesc::Reg32ID,&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|ISATOMIC|CANTHROW,kLtStore1,"stxr","0,1,2",1,StrLdr64ImmValid,kStoreExclusive,0xc8007c00) +DEFINE_MOP(MOP_wstxrb, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem8D},ISSTORE|ISATOMIC|CANTHROW,kLtStore1,"stxrb","0,1,2",1,MOP_wstxrbValid,kStoreExclusive,0x8007c00) +DEFINE_MOP(MOP_wstxrh, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem16D},ISSTORE|ISATOMIC|CANTHROW,kLtStore1,"stxrh","0,1,2",1,MOP_wstxrhValid,kStoreExclusive,0x48007c00) +DEFINE_MOP(MOP_wstxr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem32D},ISSTORE|ISATOMIC|CANTHROW,kLtStore1,"stxr","0,1,2",1,MOP_wstxrValid,kStoreExclusive,0x88007c00) +DEFINE_MOP(MOP_xstxr, {&OpndDesc::Reg32ID,&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|ISATOMIC|CANTHROW,kLtStore1,"stxr","0,1,2",1,MOP_xstxrValid,kStoreExclusive,0xc8007c00) -DEFINE_MOP(MOP_wstlxrb,{&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem8D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxrb","0,1,2",1,StrLdr8ImmValid,kStoreExclusive,0x800fc00) -DEFINE_MOP(MOP_wstlxrh,{&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem16D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxrh","0,1,2",1,StrLdr16ImmValid,kStoreExclusive,0x4800fc00) -DEFINE_MOP(MOP_wstlxr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem32D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxr","0,1,2",1,StrLdr32ImmValid,kStoreExclusive,0x8800fc00) -DEFINE_MOP(MOP_xstlxr, {&OpndDesc::Reg32ID,&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxr","0,1,2",1,StrLdr64ImmValid,kStoreExclusive,0xc800fc00) +DEFINE_MOP(MOP_wstlxrb,{&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem8D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxrb","0,1,2",1,MOP_wstlxrbValid,kStoreExclusive,0x800fc00) +DEFINE_MOP(MOP_wstlxrh,{&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem16D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxrh","0,1,2",1,MOP_wstlxrhValid,kStoreExclusive,0x4800fc00) +DEFINE_MOP(MOP_wstlxr, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Mem32D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxr","0,1,2",1,MOP_wstlxrValid,kStoreExclusive,0x8800fc00) +DEFINE_MOP(MOP_xstlxr, {&OpndDesc::Reg32ID,&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxr","0,1,2",1,MOP_xstlxrValid,kStoreExclusive,0xc800fc00) -DEFINE_MOP(MOP_wstlxp, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Mem64D},ISSTORE|ISSTOREPAIR|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxp","0,1,2,3",1,StrLdr64ImmValid,kStoreExclusivePair,0x88208000) -DEFINE_MOP(MOP_xstlxp, {&OpndDesc::Reg32ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|ISSTOREPAIR|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxp","0,1,2,3",1,StrLdr64ImmValid,kStoreExclusivePair,0xc8208000) +DEFINE_MOP(MOP_wstlxp, {&OpndDesc::Reg32ID,&OpndDesc::Reg32IS,&OpndDesc::Reg32IS,&OpndDesc::Mem64D},ISSTORE|ISSTOREPAIR|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxp","0,1,2,3",1,MOP_wstlxpValid,kStoreExclusivePair,0x88208000) +DEFINE_MOP(MOP_xstlxp, {&OpndDesc::Reg32ID,&OpndDesc::Reg64IS,&OpndDesc::Reg64IS,&OpndDesc::Mem64D},ISSTORE|ISSTOREPAIR|ISATOMIC|HASRELEASE|CANTHROW,kLtStore1,"stlxp","0,1,2,3",1,MOP_xstlxpValid,kStoreExclusivePair,0xc8208000) + +/* Generate a breakpoint instruction exception */ +/* FIXME: DEFINE_MOP(MOP_brk, {OpndDesc::Imm16}, 0, kLtAlu, "brk", "0", 1, Imm16BitValid) */ +DEFINE_MOP(MOP_brk, {&OpndDesc::Reg64VD,&OpndDesc::Imm8},ISVECTOR,kLtFpalu,"brk","0,1",1) /* Memory barriers */ /* MOP_dmb_ishld */ @@ -922,8 +932,8 @@ DEFINE_MOP(MOP_vuaddwvvu,{&OpndDesc::Reg128VD,&OpndDesc::Reg128VS,&OpndDesc::Reg DEFINE_MOP(MOP_vsaddw2vvv,{&OpndDesc::Reg128VD,&OpndDesc::Reg128VS,&OpndDesc::Reg128VS},ISVECTOR,kLtFpalu,"saddw2","0,1,2",1) DEFINE_MOP(MOP_vuaddw2vvv,{&OpndDesc::Reg128VD,&OpndDesc::Reg128VS,&OpndDesc::Reg128VS},ISVECTOR,kLtFpalu,"uaddw2","0,1,2",1) DEFINE_MOP(MOP_vaddvvv, {&OpndDesc::Reg128VD,&OpndDesc::Reg128VS,&OpndDesc::Reg128VS},ISVECTOR,kLtFpalu,"add","0,1,2",1) -DEFINE_MOP(MOP_vmuluuu, {&OpndDesc::Reg64VD,&OpndDesc::Reg64VS,&OpndDesc::Reg64VS},ISVECTOR,kLtFpalu,"mul","0,1,2",1) -DEFINE_MOP(MOP_vmulvvv, {&OpndDesc::Reg128VD,&OpndDesc::Reg128VS,&OpndDesc::Reg128VS},ISVECTOR,kLtFpalu,"mul","0,1,2",1) +DEFINE_MOP(MOP_vmuluuu, {&OpndDesc::Reg64VD,&OpndDesc::Reg64VS,&OpndDesc::Reg64VS},ISVECTOR,kLtAdvsimdMul,"mul","0,1,2",1) +DEFINE_MOP(MOP_vmulvvv, {&OpndDesc::Reg128VD,&OpndDesc::Reg128VS,&OpndDesc::Reg128VS},ISVECTOR,kLtAdvsimdMulQ,"mul","0,1,2",1) DEFINE_MOP(MOP_vsubuuu, {&OpndDesc::Reg64VD,&OpndDesc::Reg64VS,&OpndDesc::Reg64VS},ISVECTOR,kLtFpalu,"sub","0,1,2",1) DEFINE_MOP(MOP_vsubvvv, {&OpndDesc::Reg128VD,&OpndDesc::Reg128VS,&OpndDesc::Reg128VS},ISVECTOR,kLtFpalu,"sub","0,1,2",1) DEFINE_MOP(MOP_vanduuu, {&OpndDesc::Reg64VD,&OpndDesc::Reg64VS,&OpndDesc::Reg64VS},ISVECTOR,kLtFpalu,"and","0,1,2",1) @@ -1178,6 +1188,10 @@ DEFINE_MOP(MOP_pseudo_dependence_seperator, {},0,kLtUndef,"//MOP_pseudo_dependen /* MOP_pseudo_none, */ DEFINE_MOP(MOP_pseudo_none, {},0,kLtUndef,"//MOP_pseudo_none","0", 0) +/* MOP_ret_assert_nonnull*/ +/* FIXME: DEFINE_MOP(MOP_assert_nonnull, {&OpndDesc::Reg32ID, &OpndDesc::Mem32S},ISLOAD | CANTHROW | ISCALL,kLtUndef,"ldr","0,1", 1, MOP_wldrValid, MOP_wldrSplit) */ +DEFINE_MOP(MOP_assert_nonnull, {&OpndDesc::Reg32ID,&OpndDesc::Mem32S},ISLOAD|CANTHROW,kLtLoad1,"ldr","0,1",1,MOP_wldrValid, MOP_wldrSplit,kLoadStoreReg,0xb8400000) + /*MOP_nop */ DEFINE_MOP(MOP_nop, {},ISNOP,kLtAlu,"nop","", 1, kSystemInsn, 0xd503201f) diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_memlayout.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_memlayout.h index 084608845ee5a70a8d1c12cf26f803975cd6abd5..6d4ffe159cc49bdad0067393b188574444d05ccf 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_memlayout.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_memlayout.h @@ -198,9 +198,11 @@ public: return segRefLocals.GetSize(); } + uint64 GetSizeOfColdToStk() const; int32 GetRefLocBaseLoc() const; int32 GetGRSaveAreaBaseLoc(); int32 GetVRSaveAreaBaseLoc(); + int32 GetCalleeSaveBaseLoc() const override; private: MemSegment segRefLocals = MemSegment(kMsRefLocals); diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_mop_split.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_mop_split.h new file mode 100644 index 0000000000000000000000000000000000000000..d0e6456ba017512e9521a656115168edc7170fb6 --- /dev/null +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_mop_split.h @@ -0,0 +1,749 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_SPLIT_H +#define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_SPLIT_H + +#include "aarch64_cg.h" +#include "aarch64_isa.h" +#include "cg_irbuilder.h" +#include "cgbb.h" +#include "common_utils.h" + +namespace maplebe { +// Supply a new reg operand for insn split process, which type is kRegTyInt for immediate. +// Before regalloc: create a new virtual reg; +// After regalloc: use R16 to be a temporary physical reg. +inline RegOperand *GetSplitBaseReg(bool isAfterRegAlloc, bool is64Bits, OperandBuilder *opndBuilder) +{ + RegOperand *resOpnd = nullptr; + if (!isAfterRegAlloc) { + resOpnd = &opndBuilder->CreateVReg((is64Bits ? k64BitSize : k32BitSize), kRegTyInt); + } else { + resOpnd = &opndBuilder->CreatePReg(R16, (is64Bits ? k64BitSize : k32BitSize), kRegTyInt); + } + return resOpnd; +} + +// Judging valid range of the immediate by passing in bitLen & forPair parameter, return the closest valid value to +// ofstVal, getting the remainder simultaneously. The valid value will be input in new memopnd, and the remainder +// will be input in add insn. +inline ImmOperand &SplitGetRemained(const MemOperand &memOpnd, uint32 bitLen, int64 ofstVal, bool forPair, + OperandBuilder *opndBuilder) +{ + // opndVal == Q0 * 32760(16380) + R0 + // R0 == Q1 * 8(4) + R1 + // ADDEND == Q0 * 32760(16380) + R1 + // NEW_OFFSET = Q1 * 8(4) + // we want to generate two instructions: + // ADD TEMP_REG, X29, ADDEND + // LDR/STR TEMP_REG, [ TEMP_REG, #NEW_OFFSET ] + int32 maxPimm = 0; + if (!forPair) { + maxPimm = MemOperand::GetMaxPIMM(bitLen); + } else { + maxPimm = MemOperand::GetMaxPairPIMM(bitLen); + } + DEBUG_ASSERT(maxPimm != 0, "get max pimm failed"); + int64 q0 = ofstVal / maxPimm + (ofstVal < 0 ? -1 : 0); + int64 addend = q0 * maxPimm; + uint64 r0 = static_cast(ofstVal - addend); + uint64 alignment = static_cast(static_cast(MemOperand::GetImmediateOffsetAlignment(bitLen))); + auto q1 = r0 >> alignment; + auto r1 = static_cast(r0 & ((1u << alignment) - 1)); + auto remained = static_cast(q1 << alignment); + addend = addend + r1; + if (addend > 0) { + uint64 suffixClear = 0xfff; + if (forPair) { + suffixClear = 0xff; + } + int64 remainedTmp = remained + static_cast(static_cast(addend) & suffixClear); + if (!MemOperand::IsPIMMOffsetOutOfRange(static_cast(remainedTmp), bitLen) && + ((static_cast(remainedTmp) & ((1u << alignment) - 1)) == 0)) { + addend = static_cast(static_cast(addend) & ~suffixClear); + } + } + ImmOperand &immAddend = opndBuilder->CreateImm(k64BitSize, addend, true); + if (memOpnd.GetOffsetImmediate()->GetVary() == kUnAdjustVary) { + immAddend.SetVary(kUnAdjustVary); + } + return immAddend; +} + +// Split Add Insn add reg, reg, #imm, steps as follows: +// If #imm value range 0 ~ 2^24 - 1, insn will be split into add reg, reg, #imm(, LSL 12) +// If #imm value out of range 2^24, insn will be split as follows: +// add x0, x1, #imm ====> mov x2, #imm +// add x0, x1, x2 +inline void AddInsnSplit(Insn *insn, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder, + OperandBuilder *opndBuilder) +{ + if (insn->VerifySelf()) { + return; + } + Operand *opnd0 = &insn->GetOperand(kInsnFirstOpnd); + Operand *opnd1 = &insn->GetOperand(kInsnSecondOpnd); + Operand *opnd2 = &insn->GetOperand(kInsnThirdOpnd); + ImmOperand *oldImmOpnd = static_cast(opnd2); + ImmOperand *immOpnd = + &opndBuilder->CreateImm(oldImmOpnd->GetSize(), oldImmOpnd->GetValue(), oldImmOpnd->IsSignedValue()); + immOpnd->SetVary(oldImmOpnd->GetVary()); + insn->SetOperand(kInsnThirdOpnd, *immOpnd); + MOperator mOpCode = MOP_undef; + if (immOpnd->IsNegative()) { + immOpnd->Negate(); + mOpCode = is64Bits ? MOP_xsubrri12 : MOP_wsubrri12; + insn->SetMOP(AArch64CG::kMd[mOpCode]); + if (!insn->VerifySelf()) { + insn->SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder); + } + return; + } + BB *bb = insn->GetBB(); + // lower 24 bits has 1, higher bits are all 0 + if (immOpnd->IsInBitSize(kMaxImmVal24Bits, 0)) { + // lower 12 bits and higher 12 bits both has 1 + Operand *newOpnd1 = opnd1; + if (!(immOpnd->IsInBitSize(kMaxImmVal12Bits, 0) || immOpnd->IsInBitSize(kMaxImmVal12Bits, kMaxImmVal12Bits))) { + // process higher 12 bits + ImmOperand &immOpnd2 = opndBuilder->CreateImm( + immOpnd->GetSize(), static_cast(static_cast(immOpnd->GetValue()) >> kMaxImmVal12Bits), + immOpnd->IsSignedValue()); + mOpCode = is64Bits ? MOP_xaddrri24 : MOP_waddrri24; + RegOperand *tmpRes = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder); + BitShiftOperand &shiftopnd = opndBuilder->CreateBitShift(BitShiftOperand::kLSL, k12BitSize, k64BitSize); + Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *tmpRes, *opnd1, immOpnd2, shiftopnd); + newInsn.SetBB(bb); + DEBUG_ASSERT(newInsn.VerifySelf(), "immOpnd2 appears invalid"); + (void)bb->InsertInsnBefore(*insn, newInsn); + // get lower 12 bits value + immOpnd->ModuloByPow2(kMaxImmVal12Bits); + newOpnd1 = tmpRes; + } + // process lower 12 bits value + mOpCode = is64Bits ? MOP_xaddrri12 : MOP_waddrri12; + // It`s worth noting that if immOpnd->IsInBitSize(12, 12) returns true, gcc assembler can compile correctly, + // so we pass immOpnd directly as a parameter. + Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *newOpnd1, *immOpnd); + newInsn.SetBB(bb); + DEBUG_ASSERT(newInsn.VerifySelf(), "immOpnd appears invalid"); + bb->ReplaceInsn(*insn, newInsn); + return; + } else { + // load into register + int64 immVal = immOpnd->GetValue(); + int32 tail0bitNum = AArch64isa::GetTail0BitNum(immVal); + int32 head0bitNum = AArch64isa::GetHead0BitNum(immVal); + const int32 bitNum = (k64BitSizeInt - head0bitNum) - tail0bitNum; + RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder); + regno_t regNO0 = static_cast(opnd1)->GetRegisterNumber(); + // The content of the next if code block is when immvalue can be moved in one insn, we do next: + // add x0, x1, #imm1 ====> mov x2, #imm2 + // add x0, x1, x2, LSL + // #imm2 = #imm1 >> shift + // addrrrs do not support sp + if (bitNum <= k16BitSizeInt && regNO0 != RSP) { + int64 newImm = + static_cast((static_cast(immVal) >> static_cast(tail0bitNum)) & 0xFFFF); + ImmOperand &immOpnd1 = opndBuilder->CreateImm(k16BitSize, newImm, false); + mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32; + Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, immOpnd1); + movInsn.SetBB(bb); + (void)bb->InsertInsnBefore(*insn, movInsn); + mOpCode = is64Bits ? MOP_xaddrrrs : MOP_waddrrrs; + // bitLen means bitshiftopnd size: 64bits -> 6, 32bits ->5 + uint32 bitLen = is64Bits ? k6BitSize : k5BitSize; + BitShiftOperand &bitShiftOpnd = + opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast(tail0bitNum), bitLen); + Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd, bitShiftOpnd); + newInsn.SetBB(bb); + bb->ReplaceInsn(*insn, newInsn); + return; + } + mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32; + Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, *immOpnd); + movInsn.SetBB(bb); + mOpCode = is64Bits ? MOP_xaddrrr : MOP_waddrrr; + Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd); + newInsn.SetBB(bb); + (void)bb->InsertInsnBefore(*insn, movInsn); + // If #imm of mov is invalid, split mov insn + if (!movInsn.VerifySelf()) { + movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder); + } + bb->ReplaceInsn(*insn, newInsn); + } +} + +// Split Sub Insn sub reg, reg, #imm, the same split steps as add +inline void SubInsnSplit(Insn *insn, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder, + OperandBuilder *opndBuilder) +{ + if (insn->VerifySelf()) { + return; + } + Operand *opnd0 = &insn->GetOperand(kInsnFirstOpnd); + Operand *opnd1 = &insn->GetOperand(kInsnSecondOpnd); + Operand *opnd2 = &insn->GetOperand(kInsnThirdOpnd); + ImmOperand *oldImmOpnd = static_cast(opnd2); + ImmOperand *immOpnd = + &opndBuilder->CreateImm(oldImmOpnd->GetSize(), oldImmOpnd->GetValue(), oldImmOpnd->IsSignedValue()); + immOpnd->SetVary(oldImmOpnd->GetVary()); + insn->SetOperand(kInsnThirdOpnd, *immOpnd); + MOperator mOpCode = MOP_undef; + if (immOpnd->IsNegative()) { + immOpnd->Negate(); + mOpCode = is64Bits ? MOP_xaddrri12 : MOP_waddrri12; + insn->SetMOP(AArch64CG::kMd[mOpCode]); + if (!insn->VerifySelf()) { + insn->SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder); + } + return; + } + BB *bb = insn->GetBB(); + int64 higher12BitVal = static_cast(static_cast(immOpnd->GetValue()) >> kMaxImmVal12Bits); + if (immOpnd->IsInBitSize(kMaxImmVal24Bits, 0) && higher12BitVal + 1 <= kMaxPimm8) { + // SUB Wd|WSP, Wn|WSP, #imm{, shift} ; 32-bit general registers + // SUB Xd|SP, Xn|SP, #imm{, shift} ; 64-bit general registers + // imm : 0 ~ 4095, shift: none, LSL #0, or LSL #12 + // aarch64 assembly takes up to 24-bits, if the lower 12 bits is all 0 + // large offset is treated as sub (higher 12 bits + 4096) + add + // it gives opportunities for combining add + ldr due to the characteristics of aarch64's load/store + bool isSplitSub = false; + Operand *newOpnd1 = opnd1; + if (!(immOpnd->IsInBitSize(kMaxImmVal12Bits, 0) || immOpnd->IsInBitSize(kMaxImmVal12Bits, kMaxImmVal12Bits))) { + isSplitSub = true; + // process higher 12 bits + ImmOperand &immOpnd2 = + opndBuilder->CreateImm(immOpnd->GetSize(), higher12BitVal + 1, immOpnd->IsSignedValue()); + mOpCode = is64Bits ? MOP_xsubrri24 : MOP_wsubrri24; + RegOperand *resOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder); + BitShiftOperand &shiftopnd = opndBuilder->CreateBitShift(BitShiftOperand::kLSL, k12BitSize, k64BitSize); + Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *resOpnd, *opnd1, immOpnd2, shiftopnd); + newInsn.SetBB(bb); + (void)bb->InsertInsnBefore(*insn, newInsn); + immOpnd->ModuloByPow2(kMaxImmVal12Bits); + immOpnd->SetValue(static_cast(kMax12UnsignedImm) - immOpnd->GetValue()); + newOpnd1 = resOpnd; + } + // process lower 12 bits + mOpCode = isSplitSub ? (is64Bits ? MOP_xaddrri12 : MOP_waddrri12) : (is64Bits ? MOP_xsubrri12 : MOP_wsubrri12); + Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *newOpnd1, *immOpnd); + newInsn.SetBB(bb); + bb->ReplaceInsn(*insn, newInsn); + return; + } else { + // load into register + int64 immVal = immOpnd->GetValue(); + int32 tail0bitNum = AArch64isa::GetTail0BitNum(immVal); + int32 head0bitNum = AArch64isa::GetHead0BitNum(immVal); + const int32 bitNum = (k64BitSizeInt - head0bitNum) - tail0bitNum; + RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder); + // The content of the next if code block is when immvalue can be moved in one insn, we do next: + // sub x0, x1, #imm1 ====> mov x2, #imm2 + // sub x0, x1, x2, LSL + // #imm2 = #imm1 >> shift + // subrrrs supports sp, so do not need to check whether regNo is RSP + if (bitNum <= k16BitSizeInt) { + int64 newImm = + static_cast((static_cast(immVal) >> static_cast(tail0bitNum)) & 0xFFFF); + ImmOperand &immOpnd1 = opndBuilder->CreateImm(k16BitSize, newImm, false); + mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32; + Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, immOpnd1); + movInsn.SetBB(bb); + (void)bb->InsertInsnBefore(*insn, movInsn); + mOpCode = is64Bits ? MOP_xsubrrrs : MOP_wsubrrrs; + // bitLen means bitshiftopnd size: 64bits -> 6, 32bits ->5 + uint32 bitLen = is64Bits ? k6BitSize : k5BitSize; + BitShiftOperand &bitShiftOpnd = + opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast(tail0bitNum), bitLen); + Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd, bitShiftOpnd); + newInsn.SetBB(bb); + bb->ReplaceInsn(*insn, newInsn); + return; + } + mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32; + Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, *immOpnd); + movInsn.SetBB(bb); + mOpCode = is64Bits ? MOP_xsubrrr : MOP_wsubrrr; + Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *movOpnd); + newInsn.SetBB(bb); + (void)bb->InsertInsnBefore(*insn, movInsn); + // If #imm of mov is invalid, split mov insn + if (!movInsn.VerifySelf()) { + movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder); + } + bb->ReplaceInsn(*insn, newInsn); + } +} + +// adds & subs updates the condition flags based on the result, so it cannot be split into multiple instructions +// of the same type, because we don`t know when the result is out of range and changes flags. The solution is: +// adds/subs x0, x1, #imm ====> mov x2, #imm +// adds/subs x0, x1, x2 +// isAdds: true -> adds, false -> subs +inline void AddsSubsInsnSplit(Insn *insn, bool isAdds, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder, + OperandBuilder *opndBuilder) +{ + if (insn->VerifySelf()) { + return; + } + Operand *opnd0 = &insn->GetOperand(kInsnFirstOpnd); + Operand *opnd1 = &insn->GetOperand(kInsnSecondOpnd); + Operand *opnd2 = &insn->GetOperand(kInsnThirdOpnd); + Operand *opnd3 = &insn->GetOperand(kInsnFourthOpnd); + ImmOperand *immOpnd = static_cast(opnd3); + MOperator mOpCode = MOP_undef; + BB *bb = insn->GetBB(); + RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder); + mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32; + Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, *immOpnd); + movInsn.SetBB(bb); + mOpCode = isAdds ? (is64Bits ? MOP_xaddsrrr : MOP_waddsrrr) : (is64Bits ? MOP_xsubsrrr : MOP_wsubsrrr); + Insn &newInsn = insnBuilder->BuildInsn(mOpCode, *opnd0, *opnd1, *opnd2, *movOpnd); + newInsn.SetBB(bb); + (void)bb->InsertInsnBefore(*insn, movInsn); + // If #imm of mov is invalid, split mov first. + if (!movInsn.VerifySelf()) { + movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder); + } + (void)bb->InsertInsnBefore(*insn, newInsn); + bb->RemoveInsn(*insn); +} + +// Split Add/Sub Insn with BitShiftOperand (LSL 12), steps as follows: +// add/sub x0, x1, #imm, LSL 12 ====> add/sub x0, x1, #newimm ====> Add/SubInsnSplit +// isAdd: true -> add, false -> sub +inline void AddSubWithLslSplit(Insn *insn, bool isAdd, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder, + OperandBuilder *opndBuilder) +{ + if (insn->VerifySelf()) { + return; + } + uint32 size = is64Bits ? k64BitSize : k32BitSize; + ImmOperand &immOpnd = static_cast(insn->GetOperand(kInsnThirdOpnd)); + // add/sub x0, x1, #imm, LSL 12 ====> imm value range can be split: 2^12 ~ 2^52 - 1 + // add/sub w0, w1, #imm, LSL 12 ====> imm value range can be split: 2^12 ~ 2^20 - 1 + // If imm is out of range, insn will not be split + if (!immOpnd.IsInBitSize((size - k12BitSize), k0BitSize)) { + return; + } + BB *bb = insn->GetBB(); + ImmOperand &newImmOpnd = + opndBuilder->CreateImm(size, static_cast(static_cast(immOpnd.GetValue()) << k12BitSize)); + MOperator mOpCode = is64Bits ? (isAdd ? MOP_xaddrri12 : MOP_xsubrri12) : (isAdd ? MOP_waddrri12 : MOP_wsubrri12); + Insn &newInsn = insnBuilder->BuildInsn(mOpCode, insn->GetOperand(kInsnFirstOpnd), insn->GetOperand(kInsnSecondOpnd), + newImmOpnd); + newInsn.SetBB(bb); + bb->ReplaceInsn(*insn, newInsn); + if (!newInsn.VerifySelf()) { + newInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder); + } +} + +// Split memoperand with invalid offset value to a new valid memoperand and add insn with remainder. +inline MemOperand &MemOfstSplitWithAdd(const MemOperand &memOpnd, uint32 bitLen, bool isAfterRegAlloc, Insn *insn, + bool forPair, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + DEBUG_ASSERT((memOpnd.GetAddrMode() == MemOperand::kAddrModeBOi), "expect kAddrModeBOi memOpnd"); + DEBUG_ASSERT(memOpnd.IsIntactIndexed(), "expect intactIndexed memOpnd"); + BB *bb = insn->GetBB(); + OfstOperand *ofstOpnd = memOpnd.GetOffsetImmediate(); + int64 ofstVal = ofstOpnd->GetOffsetValue(); + RegOperand *resOpnd = GetSplitBaseReg(isAfterRegAlloc, true, opndBuilder); + ImmOperand &immAddend = SplitGetRemained(memOpnd, bitLen, ofstVal, forPair, opndBuilder); + int64 remained = (ofstVal - immAddend.GetValue()); + RegOperand *origBaseReg = memOpnd.GetBaseRegister(); + DEBUG_ASSERT(origBaseReg != nullptr, "nullptr check"); + // Provide add insn to split offset, where add insn is 64-bit explicitly + Insn &addInsn = insnBuilder->BuildInsn(MOP_xaddrri12, *resOpnd, *origBaseReg, immAddend); + addInsn.SetBB(bb); + bb->InsertInsnBefore(*insn, addInsn); + if (!addInsn.VerifySelf()) { + addInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder); + } + ImmOperand &remainedOpnd = opndBuilder->CreateImm(k32BitSize, remained, true); + MemOperand &newMemOpnd = opndBuilder->CreateMem(bitLen, *resOpnd, remainedOpnd); + newMemOpnd.SetStackMem(memOpnd.IsStackMem()); + return newMemOpnd; +} + +// Split a load/store insn with invalid offset value to a new valid insn and add insn. +// idx: memOperand index of insn +inline void LoadStoreInsnSplit(Insn *insn, uint32 idx, bool forPair, bool isAfterRegAlloc, InsnBuilder *insnBuilder, + OperandBuilder *opndBuilder) +{ + if (insn->VerifySelf()) { + return; + } + MemOperand &memOpnd = static_cast(insn->GetOperand(idx)); + if (!(memOpnd.GetAddrMode() == MemOperand::kAddrModeBOi && memOpnd.IsIntactIndexed())) { + return; + } + uint32 bitLen = insn->GetDesc()->GetOpndDes(idx)->GetSize(); + MemOperand &newMemOpnd = + MemOfstSplitWithAdd(memOpnd, bitLen, isAfterRegAlloc, insn, forPair, insnBuilder, opndBuilder); + insn->SetOperand(idx, newMemOpnd); +} + +// ccmp updates the condition flags based on the result, so it cannot be split into multiple instructions +// of the same type, because we don`t know when the result is out of range and changes flags. The solution is: +// ccmp , #, #, ====> mov , # +// ccmp , , #, +inline void CondCompareInsnSplit(Insn *insn, bool is64Bits, bool isAfterRegAlloc, InsnBuilder *insnBuilder, + OperandBuilder *opndBuilder) +{ + if (insn->VerifySelf()) { + return; + } + ImmOperand &immOpnd = static_cast(insn->GetOperand(kInsnSecondOpnd)); + MOperator mOpCode = MOP_undef; + BB *bb = insn->GetBB(); + RegOperand *movOpnd = GetSplitBaseReg(isAfterRegAlloc, is64Bits, opndBuilder); + mOpCode = is64Bits ? MOP_xmovri64 : MOP_wmovri32; + Insn &movInsn = insnBuilder->BuildInsn(mOpCode, *movOpnd, immOpnd); + movInsn.SetBB(bb); + bb->InsertInsnBefore(*insn, movInsn); + if (!movInsn.VerifySelf()) { + movInsn.SplitSelf(isAfterRegAlloc, insnBuilder, opndBuilder); + } + mOpCode = is64Bits ? MOP_xccmprric : MOP_wccmprric; + insn->SetMOP(AArch64CG::kMd[mOpCode]); + insn->SetOperand(kInsnSecondOpnd, *movOpnd); +} + +// split mov w0, #imm to mov and movk +inline void MOP_wmovri32Split(Insn *curInsn, bool /* isAfterRegAlloc */, InsnBuilder *insnBuilder, + OperandBuilder *opndBuilder) +{ + // If higher 32bits of immVal have 1, we will truncate and keep lower 32 bits. + int64 immVal = static_cast( + static_cast(static_cast(curInsn->GetOperand(kInsnSecondOpnd)).GetValue()) & + 0x00000000FFFFFFFFULL); + ImmOperand &immOpnd = opndBuilder->CreateImm(k64BitSize, immVal, true); + curInsn->SetOperand(kInsnSecondOpnd, immOpnd); + if (curInsn->VerifySelf()) { + return; + } + RegOperand &destReg = static_cast(curInsn->GetOperand(kInsnFirstOpnd)); + auto *bb = curInsn->GetBB(); + uint64 chunkVal0 = static_cast(immVal) & 0x0000FFFFULL; + ImmOperand &src0 = opndBuilder->CreateImm(k16BitSize, static_cast(chunkVal0), false); + Insn &movInsn = insnBuilder->BuildInsn(MOP_wmovri32, destReg, src0); + movInsn.SetBB(bb); + (void)bb->InsertInsnBefore(*curInsn, movInsn); + uint64 chunkVal1 = (static_cast(immVal) >> k16BitSize) & 0x0000FFFFULL; + ImmOperand &src16 = opndBuilder->CreateImm(k16BitSize, static_cast(chunkVal1), false); + BitShiftOperand *lslOpnd = &opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast(k16BitSize), 6); + Insn &movkInsn = insnBuilder->BuildInsn(MOP_wmovkri16, destReg, src16, *lslOpnd); + movkInsn.SetBB(bb); + (void)bb->InsertInsnBefore(*curInsn, movkInsn); + bb->RemoveInsn(*curInsn); +} + +// split mov x0, #imm to movz/movn and movk +inline void MOP_xmovri64Split(Insn *curInsn, bool /* isAfterRegAlloc */, InsnBuilder *insnBuilder, + OperandBuilder *opndBuilder) +{ + if (curInsn->VerifySelf()) { + return; + } + RegOperand &destReg = static_cast(curInsn->GetOperand(kInsnFirstOpnd)); + int64 immVal = static_cast(curInsn->GetOperand(kInsnSecondOpnd)).GetValue(); + bool useMovz = BetterUseMOVZ(static_cast(immVal)); + bool useMovk = false; + // get lower 32 bits of the immediate + uint64 chunkLval = static_cast(immVal) & 0xFFFFFFFFULL; + // get upper 32 bits of the immediate + uint64 chunkHval = (static_cast(immVal) >> k32BitSize) & 0xFFFFFFFFULL; + int32 maxLoopTime = 4; + if (chunkLval == chunkHval) { + // compute lower 32 bits, and then copy to higher 32 bits, so only 2 chunks need be processed + maxLoopTime = 2; + } + uint64 sa = 0; + auto *bb = curInsn->GetBB(); + for (int64 i = 0; i < maxLoopTime; ++i, sa += k16BitSize) { + // create an imm opereand which represents the i-th 16-bit chunk of the immediate + uint64 chunkVal = (static_cast(immVal) >> sa) & 0x0000FFFFULL; + if (useMovz ? (chunkVal == 0) : (chunkVal == 0x0000FFFFULL)) { + continue; + } + ImmOperand &src16 = opndBuilder->CreateImm(k16BitSize, static_cast(chunkVal), false); + BitShiftOperand *lslOpnd = &opndBuilder->CreateBitShift(BitShiftOperand::kLSL, static_cast(sa), 6); + Insn *newInsn = nullptr; + if (!useMovk) { + // use movz or movn + if (!useMovz) { + src16.BitwiseNegate(); + } + MOperator mOpCode = useMovz ? MOP_xmovzri16 : MOP_xmovnri16; + newInsn = &insnBuilder->BuildInsn(mOpCode, destReg, src16, *lslOpnd); + newInsn->SetBB(bb); + useMovk = true; + } else { + newInsn = &insnBuilder->BuildInsn(MOP_xmovkri16, destReg, src16, *lslOpnd); + newInsn->SetBB(bb); + } + (void)bb->InsertInsnBefore(*curInsn, *newInsn); + } + constexpr int32 loopTime = 2; + if (maxLoopTime == loopTime) { + // copy lower 32 bits to higher 32 bits + ImmOperand &immOpnd = opndBuilder->CreateImm(k8BitSize, k32BitSize, false); + Insn &insn = insnBuilder->BuildInsn(MOP_xbfirri6i6, destReg, destReg, immOpnd, immOpnd); + insn.SetBB(bb); + (void)bb->InsertInsnBefore(*curInsn, insn); + } + bb->RemoveInsn(*curInsn); +} + +inline void MOP_xaddrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + AddSubWithLslSplit(insn, true, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xaddrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + AddInsnSplit(insn, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xaddsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + AddsSubsInsnSplit(insn, true, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_waddrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + AddSubWithLslSplit(insn, true, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_waddrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + AddInsnSplit(insn, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_waddsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + AddsSubsInsnSplit(insn, true, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xsubrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + AddSubWithLslSplit(insn, false, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xsubrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + SubInsnSplit(insn, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xsubsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + AddsSubsInsnSplit(insn, false, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wsubrri24Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + AddSubWithLslSplit(insn, false, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wsubrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + SubInsnSplit(insn, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wsubsrri12Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + AddsSubsInsnSplit(insn, false, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wldrsbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xldrsbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wldrbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wldrshSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xldrshSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xldrswSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wldrhSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_bldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_hldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_sldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_dldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_qldrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xldpswSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_sldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_dldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_qldpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wccmpriicSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + CondCompareInsnSplit(insn, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xccmpriicSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + CondCompareInsnSplit(insn, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wstrbSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wstrhSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_sstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_dstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_qstrSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnSecondOpnd, false, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_wstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_xstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_sstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_dstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_qstpSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) +{ + LoadStoreInsnSplit(insn, kInsnThirdOpnd, true, isAfterRegAlloc, insnBuilder, opndBuilder); +} + +inline void MOP_DEBUG_ASSERT_nonnullSplit(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, + OperandBuilder *opndBuilder) +{ + MOP_wldrSplit(insn, isAfterRegAlloc, insnBuilder, opndBuilder); +} +} /* namespace maplebe */ +#endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_SPLIT_H */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_mop_valid.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_mop_valid.h new file mode 100644 index 0000000000000000000000000000000000000000..3bfe683b91a04d983c9e1a9293b39f7d9a7a1661 --- /dev/null +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_mop_valid.h @@ -0,0 +1,1352 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_VALID_H +#define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_VALID_H +#include "aarch64_imm_valid.h" +#include "aarch64_isa.h" +#include "mempool_allocator.h" +#include "operand.h" + +namespace maplebe { +// Immediate verification for a byte from/to memory. simm: -256 ~ 255; pimm: 0 ~ 4095. +inline bool StrLdr8Valid(Operand *o) +{ + return (static_cast(o)->GetAddrMode() == MemOperand::kAddrModeLo12Li) || + StrLdrInsnSignedOfstValid(AArch64isa::GetMemOpndOffsetValue(o), k0ByteSize, + static_cast(o)->IsIntactIndexed()); +} + +// Immediate verification for half word from/to memory. simm: -256 ~ 255; pimm: 0 ~ 8190, multiple of 2. +inline bool StrLdr16Valid(Operand *o) +{ + MemOperand *memOpnd = static_cast(o); + if (memOpnd->GetAddrMode() == MemOperand::kAddrModeLo12Li) { + uint8 symAlign = 0; + const MIRSymbol *sym = memOpnd->GetSymbol(); + if (sym) { + symAlign = 1U << sym->GetSymbolAlign(CGOptions::IsArm64ilp32()); + } + return ((symAlign + static_cast(AArch64isa::GetMemOpndOffsetValue(o))) & + static_cast(k1BitSize)) == static_cast(k0BitSize); + } + return StrLdrInsnSignedOfstValid(AArch64isa::GetMemOpndOffsetValue(o), k1ByteSize, memOpnd->IsIntactIndexed()); +} + +// Immediate verification for a word from/to memory. simm: -256 ~ 255; pimm: 0 ~ 16380, multiple of 4. +inline bool StrLdr32Valid(Operand *o) +{ + MemOperand *memOpnd = static_cast(o); + if (memOpnd->GetAddrMode() == MemOperand::kAddrModeLo12Li) { + uint8 symAlign = 0; + const MIRSymbol *sym = memOpnd->GetSymbol(); + if (sym) { + symAlign = 1U << sym->GetSymbolAlign(CGOptions::IsArm64ilp32()); + } + return ((symAlign + static_cast(AArch64isa::GetMemOpndOffsetValue(o))) & + static_cast(k3BitSize)) == static_cast(k0BitSize); + } + return StrLdrInsnSignedOfstValid(AArch64isa::GetMemOpndOffsetValue(o), k2ByteSize, memOpnd->IsIntactIndexed()); +} + +// Immediate verification: value range -256 ~ 252, multiple of 4. +inline bool StrLdr32PairValid(Operand *o) +{ + constexpr int sImmValidOffset = 3; + int64 value = AArch64isa::GetMemOpndOffsetValue(o); + if ((value <= kMaxSimm32Pair) && (value >= kMinSimm32)) { + return (static_cast(value) & sImmValidOffset) > 0 ? false : true; + } + return false; +} + +// Immediate verification for 2 words from/to memory. simm: -256 ~ 255; pimm: 0 ~ 32760, multiple of 8. +inline bool StrLdr64Valid(Operand *o) +{ + MemOperand *memOpnd = static_cast(o); + if (memOpnd->GetAddrMode() == MemOperand::kAddrModeLo12Li) { + uint8 symAlign = 0; + const MIRSymbol *sym = memOpnd->GetSymbol(); + if (sym) { + symAlign = 1U << sym->GetSymbolAlign(CGOptions::IsArm64ilp32()); + } + return ((symAlign + static_cast(AArch64isa::GetMemOpndOffsetValue(o))) & + static_cast(k7BitSize)) == static_cast(k0BitSize); + } + return StrLdrInsnSignedOfstValid(AArch64isa::GetMemOpndOffsetValue(o), k3ByteSize, memOpnd->IsIntactIndexed()); +} + +// Immediate verification: value range -512 ~ 504, multiple of 8. +inline bool StrLdr64PairValid(Operand *o) +{ + constexpr int sImmValidOffset = 7; + int64 value = AArch64isa::GetMemOpndOffsetValue(o); + if (value <= kMaxSimm64Pair && (value >= kMinSimm64)) { + return (static_cast(value) & sImmValidOffset) > 0 ? false : true; + } + return false; +} + +// Immediate verification for 4 words from/to memory. simm: -256 ~ 255; pimm: 0 ~ 65520, multiple of 16. +inline bool StrLdr128Valid(Operand *o) +{ + MemOperand *memOpnd = static_cast(o); + if (memOpnd->GetAddrMode() == MemOperand::kAddrModeLo12Li) { + uint8 symAlign = 0; + const MIRSymbol *sym = memOpnd->GetSymbol(); + if (sym && sym->IsConst()) { + symAlign = 1U << sym->GetSymbolAlign(CGOptions::IsArm64ilp32()); + } + return ((symAlign + static_cast(AArch64isa::GetMemOpndOffsetValue(o))) & + static_cast(k15BitSize)) == static_cast(k0BitSize); + } + return StrLdrInsnSignedOfstValid(AArch64isa::GetMemOpndOffsetValue(o), k4ByteSize, memOpnd->IsIntactIndexed()); +} + +// Immediate verification: value range -1024 ~ 1008, multiple of 16. +inline bool StrLdr128PairValid(Operand *o) +{ + int64 value = AArch64isa::GetMemOpndOffsetValue(o); + if (value < k1024BitSize && (value >= kNegative1024BitSize)) { + return (static_cast(value) & 0xf) > 0 ? false : true; + } + return false; +} + +// Load-Acquire & Store-Release & Load/Store-Exclusive offset value must be #0 if not absent +inline bool IsOfstZero(Operand *o) +{ + int64 value = AArch64isa::GetMemOpndOffsetValue(o); + if (value == static_cast(k0BitSize)) { + return true; + } + return false; +} + +inline bool MOP_wmovri32Valid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? IsSingleInstructionMovable32(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + return checkSecond; +} + +inline bool MOP_xmovri64Valid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? IsSingleInstructionMovable64(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + return checkSecond; +} + +inline bool MOP_xaddrrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift6BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xaddsrrrsValid(const MapleVector &opnds) +{ + bool checkFifth = (opnds[kInsnFifthOpnd] != nullptr) + ? BitShift6BitValid(static_cast(opnds[kInsnFifthOpnd])->GetValue()) + : true; + return checkFifth; +} + +inline bool MOP_xxwaddrrreValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? ExtendShift0To4Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xaddrri24Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? LeftShift12Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; +} + +inline bool MOP_xaddrri12Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_xaddsrri12Valid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_waddrrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift5BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_waddsrrrsValid(const MapleVector &opnds) +{ + bool checkFifth = (opnds[kInsnFifthOpnd] != nullptr) + ? BitShift5BitValid(static_cast(opnds[kInsnFifthOpnd])->GetValue()) + : true; + return checkFifth; +} + +inline bool MOP_wwwaddrrreValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? ExtendShift0To4Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_waddrri24Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? LeftShift12Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; +} + +inline bool MOP_waddrri12Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_waddsrri12Valid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xsubrrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift6BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xsubsrrrsValid(const MapleVector &opnds) +{ + bool checkFifth = (opnds[kInsnFifthOpnd] != nullptr) + ? BitShift6BitValid(static_cast(opnds[kInsnFifthOpnd])->GetValue()) + : true; + return checkFifth; +} + +inline bool MOP_xsubrri24Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? LeftShift12Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; +} + +inline bool MOP_xsubsrri24Valid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + bool checkFifth = (opnds[kInsnFifthOpnd] != nullptr) + ? LeftShift12Valid(static_cast(opnds[kInsnFifthOpnd])->GetValue()) + : true; + return checkFourth && checkFifth; +} + +inline bool MOP_xsubrri12Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_xsubsrri12Valid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_wsubrrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift5BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_wsubsrrrsValid(const MapleVector &opnds) +{ + bool checkFifth = (opnds[kInsnFifthOpnd] != nullptr) + ? BitShift5BitValid(static_cast(opnds[kInsnFifthOpnd])->GetValue()) + : true; + return checkFifth; +} + +inline bool MOP_wsubrri24Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? LeftShift12Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; +} + +inline bool MOP_wsubsrri24Valid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + bool checkFifth = (opnds[kInsnFifthOpnd] != nullptr) + ? LeftShift12Valid(static_cast(opnds[kInsnFifthOpnd])->GetValue()) + : true; + return checkFourth && checkFifth; +} + +inline bool MOP_wsubrri12Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wsubsrri12Valid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xxwsubrrreValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? ExtendShift0To4Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_wwwsubrrreValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? ExtendShift0To4Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xandrrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift6BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xandrri13Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm13BitMaskValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wandrrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift5BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_wandrri12Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitMaskValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_xiorrrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift6BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xiorrri13Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm13BitMaskValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wiorrrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift5BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_wiorrri12Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitMaskValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_xeorrrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift6BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xeorrri13Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm13BitMaskValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_weorrrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift5BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_weorrri12Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitMaskValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wubfxrri5i5Valid(const MapleVector &opnds) +{ + if ((opnds[kInsnThirdOpnd] != nullptr) && (opnds[kInsnFourthOpnd] != nullptr)) { + int64 lsb = static_cast(opnds[kInsnThirdOpnd])->GetValue(); + int64 width = static_cast(opnds[kInsnFourthOpnd])->GetValue(); + return Lsb5BitValid(lsb) && Width5BitValid(width, lsb); + } else { + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Lsb5BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Width5BitOnlyValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; + } +} + +inline bool MOP_xubfxrri6i6Valid(const MapleVector &opnds) +{ + if ((opnds[kInsnThirdOpnd] != nullptr) && (opnds[kInsnFourthOpnd] != nullptr)) { + int64 lsb = static_cast(opnds[kInsnThirdOpnd])->GetValue(); + int64 width = static_cast(opnds[kInsnFourthOpnd])->GetValue(); + return Lsb6BitValid(lsb) && Width6BitValid(width, lsb); + } else { + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Lsb6BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Width6BitOnlyValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; + } +} + +inline bool MOP_wsbfxrri5i5Valid(const MapleVector &opnds) +{ + if ((opnds[kInsnThirdOpnd] != nullptr) && (opnds[kInsnFourthOpnd] != nullptr)) { + int64 lsb = static_cast(opnds[kInsnThirdOpnd])->GetValue(); + int64 width = static_cast(opnds[kInsnFourthOpnd])->GetValue(); + return Lsb5BitValid(lsb) && Width5BitValid(width, lsb); + } else { + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Lsb5BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Width5BitOnlyValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; + } +} + +inline bool MOP_xsbfxrri6i6Valid(const MapleVector &opnds) +{ + if ((opnds[kInsnThirdOpnd] != nullptr) && (opnds[kInsnFourthOpnd] != nullptr)) { + int64 lsb = static_cast(opnds[kInsnThirdOpnd])->GetValue(); + int64 width = static_cast(opnds[kInsnFourthOpnd])->GetValue(); + return Lsb6BitValid(lsb) && Width6BitValid(width, lsb); + } else { + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Lsb6BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Width6BitOnlyValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; + } +} + +inline bool MOP_wubfizrri5i5Valid(const MapleVector &opnds) +{ + if ((opnds[kInsnThirdOpnd] != nullptr) && (opnds[kInsnFourthOpnd] != nullptr)) { + int64 lsb = static_cast(opnds[kInsnThirdOpnd])->GetValue(); + int64 width = static_cast(opnds[kInsnFourthOpnd])->GetValue(); + return Lsb5BitValid(lsb) && Width5BitValid(width, lsb); + } else { + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Lsb5BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Width5BitOnlyValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; + } +} + +inline bool MOP_xubfizrri6i6Valid(const MapleVector &opnds) +{ + if ((opnds[kInsnThirdOpnd] != nullptr) && (opnds[kInsnFourthOpnd] != nullptr)) { + int64 lsb = static_cast(opnds[kInsnThirdOpnd])->GetValue(); + int64 width = static_cast(opnds[kInsnFourthOpnd])->GetValue(); + return Lsb6BitValid(lsb) && Width6BitValid(width, lsb); + } else { + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Lsb6BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Width6BitOnlyValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; + } +} + +inline bool MOP_wsbfizrri5i5Valid(const MapleVector &opnds) +{ + if ((opnds[kInsnThirdOpnd] != nullptr) && (opnds[kInsnFourthOpnd] != nullptr)) { + int64 lsb = static_cast(opnds[kInsnThirdOpnd])->GetValue(); + int64 width = static_cast(opnds[kInsnFourthOpnd])->GetValue(); + return Lsb5BitValid(lsb) && Width5BitValid(width, lsb); + } else { + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Lsb5BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Width5BitOnlyValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; + } +} + +inline bool MOP_xsbfizrri6i6Valid(const MapleVector &opnds) +{ + if ((opnds[kInsnThirdOpnd] != nullptr) && (opnds[kInsnFourthOpnd] != nullptr)) { + int64 lsb = static_cast(opnds[kInsnThirdOpnd])->GetValue(); + int64 width = static_cast(opnds[kInsnFourthOpnd])->GetValue(); + return Lsb6BitValid(lsb) && Width6BitValid(width, lsb); + } else { + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Lsb6BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Width6BitOnlyValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; + } +} + +inline bool MOP_wbfirri5i5Valid(const MapleVector &opnds) +{ + if ((opnds[kInsnThirdOpnd] != nullptr) && (opnds[kInsnFourthOpnd] != nullptr)) { + int64 lsb = static_cast(opnds[kInsnThirdOpnd])->GetValue(); + int64 width = static_cast(opnds[kInsnFourthOpnd])->GetValue(); + return Lsb5BitValid(lsb) && Width5BitValid(width, lsb); + } else { + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Lsb5BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Width5BitOnlyValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; + } +} + +inline bool MOP_xbfirri6i6Valid(const MapleVector &opnds) +{ + if ((opnds[kInsnThirdOpnd] != nullptr) && (opnds[kInsnFourthOpnd] != nullptr)) { + int64 lsb = static_cast(opnds[kInsnThirdOpnd])->GetValue(); + int64 width = static_cast(opnds[kInsnFourthOpnd])->GetValue(); + return Lsb6BitValid(lsb) && Width6BitValid(width, lsb); + } else { + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Lsb6BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Width6BitOnlyValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; + } +} + +inline bool MOP_xlslrri6Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? BitShift6BitValidImm(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wlslrri5Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? BitShift5BitValidImm(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_xasrrri6Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? BitShift6BitValidImm(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wasrrri5Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? BitShift5BitValidImm(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_xlsrrri6Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? BitShift6BitValidImm(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wlsrrri5Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? BitShift5BitValidImm(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wtstri32Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitMaskValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_xtstri64Valid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm13BitMaskValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wextrrrri5Valid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Lsb5BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xextrrrri6Valid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Lsb6BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_winegrrsValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? BitShift5BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_xinegrrsValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? BitShift6BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wldrsbValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr8Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_xldrsbValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr8Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldrbValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr8Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldrshValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr16Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_xldrshValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr16Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_xldrswValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr32Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldrhValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr16Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr32Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_xldrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr64Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_bldrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr8Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_hldrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr16Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_sldrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr32Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_dldrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr64Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_qldrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr128Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? StrLdr32PairValid(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_xldpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? StrLdr64PairValid(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_xldpswValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? StrLdr32PairValid(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_sldpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? StrLdr32PairValid(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_dldpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? StrLdr64PairValid(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_qldpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? StrLdr128PairValid(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_wldarbValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldarhValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldarValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_xldarValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wmovkri16Valid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? Imm16BitValid(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? ImmShift32Valid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkSecond && checkThird; +} + +inline bool MOP_xmovkri16Valid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? Imm16BitValid(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? ImmShift64Valid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkSecond && checkThird; +} + +inline bool MOP_wmovzri16Valid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? Imm16BitValid(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? ImmShift32Valid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkSecond && checkThird; +} + +inline bool MOP_xmovzri16Valid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? Imm16BitValid(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? ImmShift64Valid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkSecond && checkThird; +} + +inline bool MOP_wmovnri16Valid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? Imm16BitValid(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? ImmShift32Valid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkSecond && checkThird; +} + +inline bool MOP_xmovnri16Valid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? Imm16BitValid(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? ImmShift64Valid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkSecond && checkThird; +} + +inline bool MOP_wldxrbValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldxrhValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldxrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_xldxrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldaxrbValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldaxrhValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldaxrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_xldaxrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wldaxpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? IsOfstZero(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_xldaxpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? IsOfstZero(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_wcmpriValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wcmprrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift5BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_wwcmprreValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? ExtendShift0To4Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xcmpriValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_xcmprrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift6BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xwcmprreValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? ExtendShift0To4Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_wccmpriicValid(const MapleVector &opnds) +{ + // Is a five bit unsigned (positive) immediate, range 0 to 31 + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? BitShift5BitValidImm(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Nzcv4BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; +} + +inline bool MOP_wccmprricValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Nzcv4BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xccmpriicValid(const MapleVector &opnds) +{ + // Is a five bit unsigned (positive) immediate, range 0 to 31 + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? BitShift5BitValidImm(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Nzcv4BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkThird && checkFourth; +} + +inline bool MOP_xccmprricValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? Nzcv4BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_wcmnriValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_wcmnrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift5BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_wwcmnrreValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? ExtendShift0To4Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xcmnriValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) + ? Imm12BitValid(static_cast(opnds[kInsnThirdOpnd])->GetValue()) + : true; + return checkThird; +} + +inline bool MOP_xcmnrrsValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? BitShift6BitValid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_xwcmnrreValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) + ? ExtendShift0To4Valid(static_cast(opnds[kInsnFourthOpnd])->GetValue()) + : true; + return checkFourth; +} + +inline bool MOP_wtbnzValid(const MapleVector &opnds) +{ + // Is the bit number to be tested, in the range 0 to 63 + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? BitShift5BitValidImm(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + return checkSecond; +} + +inline bool MOP_xtbnzValid(const MapleVector &opnds) +{ + // Is the bit number to be tested, in the range 0 to 63 + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? BitShift6BitValidImm(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + return checkSecond; +} + +inline bool MOP_wtbzValid(const MapleVector &opnds) +{ + // Is the bit number to be tested, in the range 0 to 31 + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? BitShift5BitValidImm(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + return checkSecond; +} + +inline bool MOP_xtbzValid(const MapleVector &opnds) +{ + // Is the bit number to be tested, in the range 0 to 63 + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) + ? BitShift6BitValidImm(static_cast(opnds[kInsnSecondOpnd])->GetValue()) + : true; + return checkSecond; +} + +inline bool MOP_wstrbValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr8Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wstrhValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr16Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wstrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr32Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_xstrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr64Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_sstrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr32Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_dstrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr64Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_qstrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? StrLdr128Valid(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wstpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? StrLdr32PairValid(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_xstpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? StrLdr64PairValid(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_sstpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? StrLdr32PairValid(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_dstpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? StrLdr64PairValid(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_qstpValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? StrLdr128PairValid(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_wstlrbValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wstlrhValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wstlrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_xstlrValid(const MapleVector &opnds) +{ + bool checkSecond = (opnds[kInsnSecondOpnd] != nullptr) ? IsOfstZero(opnds[kInsnSecondOpnd]) : true; + return checkSecond; +} + +inline bool MOP_wstxrbValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? IsOfstZero(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_wstxrhValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? IsOfstZero(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_wstxrValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? IsOfstZero(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_xstxrValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? IsOfstZero(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_wstlxrbValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? IsOfstZero(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_wstlxrhValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? IsOfstZero(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_wstlxrValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? IsOfstZero(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_xstlxrValid(const MapleVector &opnds) +{ + bool checkThird = (opnds[kInsnThirdOpnd] != nullptr) ? IsOfstZero(opnds[kInsnThirdOpnd]) : true; + return checkThird; +} + +inline bool MOP_wstlxpValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) ? IsOfstZero(opnds[kInsnFourthOpnd]) : true; + return checkFourth; +} + +inline bool MOP_xstlxpValid(const MapleVector &opnds) +{ + bool checkFourth = (opnds[kInsnFourthOpnd] != nullptr) ? IsOfstZero(opnds[kInsnFourthOpnd]) : true; + return checkFourth; +} + +inline bool MOP_brkValid(const MapleVector &opnds) +{ + bool checkFirst = (opnds[kInsnFirstOpnd] != nullptr) + ? Imm16BitValidImm(static_cast(opnds[kInsnFirstOpnd])->GetValue()) + : true; + return checkFirst; +} + +inline bool MOP_assert_nonnullValid(const MapleVector &opnds) +{ + return MOP_wldrValid(opnds); +} +} /* namespace maplebe */ +#endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_MOP_VALID_H */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_proepilog.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_proepilog.h index 1b3d43844b30e64df45ac3e463b5892cd41e6d16..1301f7f7a00405da4de21b498a449d0b025b9f80 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_proepilog.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_proepilog.h @@ -38,6 +38,16 @@ public: stackBaseReg = useFP ? R29 : RSP; } exitBB2CallSitesMap.clear(); + AArch64CGFunc &aarchCGFunc = static_cast(func); + const MapleVector &calleeSavedRegs = aarchCGFunc.GetCalleeSavedRegs(); + if (useFP) { + storeFP = true; + } else if (find(calleeSavedRegs.begin(), calleeSavedRegs.end(), RFP) != calleeSavedRegs.end()) { + storeFP = true; + } else if (find(calleeSavedRegs.begin(), calleeSavedRegs.end(), R29) != calleeSavedRegs.end()) { + storeFP = true; + } + aarchCGFunc.SetStoreFP(storeFP); } ~AArch64GenProEpilog() override = default; @@ -112,6 +122,11 @@ private: BB *curTailcallExitBB = nullptr; BB *fastPathReturnBB = nullptr; bool useFP = true; + // To be compatible with previous code more easily,we use storeFP boolean to indicate the case + // (1) use FP to address + // (2) FP is clobbered + // need to delete this and optimize the callee save process. + bool storeFP = false; /* frame pointer(x29) is available as a general-purpose register if useFP is set as false */ AArch64reg stackBaseReg = RFP; }; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_schedule.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_schedule.h index c53bc8d59e9d4efdb88cb2adb85ac3737d7b01b5..165ec4ebe51667fadbd06c8e7cf6e4013a3a0f9e 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_schedule.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_schedule.h @@ -28,140 +28,23 @@ enum RegisterType : uint8 { kRegisterLast, }; -class ScheduleProcessInfo { -public: - explicit ScheduleProcessInfo(uint32 size) - { - availableReadyList.reserve(size); - scheduledNodes.reserve(size); - } - - virtual ~ScheduleProcessInfo() = default; - - uint32 GetLastUpdateCycle() const - { - return lastUpdateCycle; - } - - void SetLastUpdateCycle(uint32 updateCycle) - { - lastUpdateCycle = updateCycle; - } - - uint32 GetCurrCycle() const - { - return currCycle; - } - - void IncCurrCycle() - { - ++currCycle; - } - - void DecAdvanceCycle() - { - advanceCycle--; - } - - uint32 GetAdvanceCycle() const - { - return advanceCycle; - } - - void SetAdvanceCycle(uint32 cycle) - { - advanceCycle = cycle; - } - - void ClearAvailableReadyList() - { - availableReadyList.clear(); - } - - void PushElemIntoAvailableReadyList(DepNode *node) - { - availableReadyList.emplace_back(node); - } - - size_t SizeOfAvailableReadyList() const - { - return availableReadyList.size(); - } - - bool AvailableReadyListIsEmpty() const - { - return availableReadyList.empty(); - } - - void SetAvailableReadyList(const std::vector &tempReadyList) - { - availableReadyList = tempReadyList; - } - - const std::vector &GetAvailableReadyList() const - { - return availableReadyList; - } - - const std::vector &GetAvailableReadyList() - { - return availableReadyList; - } - - void PushElemIntoScheduledNodes(DepNode *node) - { - node->SetState(kScheduled); - node->SetSchedCycle(currCycle); - node->OccupyUnits(); - scheduledNodes.emplace_back(node); - } - - bool IsFirstSeparator() const - { - return isFirstSeparator; - } - - void ResetIsFirstSeparator() - { - isFirstSeparator = false; - } - - size_t SizeOfScheduledNodes() const - { - return scheduledNodes.size(); - } - - const std::vector &GetScheduledNodes() const - { - return scheduledNodes; - } - -private: - std::vector availableReadyList; - std::vector scheduledNodes; - uint32 lastUpdateCycle = 0; - uint32 currCycle = 0; - uint32 advanceCycle = 0; - bool isFirstSeparator = true; -}; - class AArch64ScheduleProcessInfo : public ScheduleProcessInfo { public: explicit AArch64ScheduleProcessInfo(uint32 size) : ScheduleProcessInfo(size) {} ~AArch64ScheduleProcessInfo() override = default; /* recover register type which is not recorded in live analysis */ - static RegType GetRegisterType(CGFunc &f, regno_t regNO); - void VaryLiveRegSet(CGFunc &f, regno_t regNO, bool isInc); - void VaryFreeRegSet(CGFunc &f, std::set regNOs, DepNode &node); + static RegType GetRegisterType(const CGFunc &f, regno_t regNO); + void VaryLiveRegSet(const CGFunc &f, regno_t regNO, bool isInc); + void VaryFreeRegSet(const CGFunc &f, std::set regNOs, DepNode &node); uint32 GetFreeIntRegs(DepNode &node) { - return freeIntRegNodeSet.count(&node) ? freeIntRegNodeSet.find(&node)->second : 0; + return (freeIntRegNodeSet.count(&node)) > 0 ? freeIntRegNodeSet.find(&node)->second : 0; } void IncFreeIntRegNode(DepNode &node) { - if (!freeIntRegNodeSet.count(&node)) { + if (freeIntRegNodeSet.count(&node) == 0) { freeIntRegNodeSet.emplace(std::pair(&node, 1)); } else { freeIntRegNodeSet.find(&node)->second++; @@ -173,7 +56,7 @@ public: } void IncFreeFpRegNode(DepNode &node) { - if (!freeFpRegNodeSet.count(&node)) { + if (freeFpRegNodeSet.count(&node) == 0) { freeFpRegNodeSet.emplace(std::pair(&node, 1)); } else { freeFpRegNodeSet.find(&node)->second++; @@ -181,7 +64,7 @@ public: } uint32 GetFreeFpRegs(DepNode &node) { - return freeFpRegNodeSet.count(&node) ? freeFpRegNodeSet.find(&node)->second : 0; + return (freeFpRegNodeSet.count(&node)) > 0 ? freeFpRegNodeSet.find(&node)->second : 0; } const std::map &GetFreeFpRegNodeSet() const { @@ -302,18 +185,18 @@ private: void CountUnitKind(const DepNode &depNode, uint32 array[], const uint32 arraySize) const override; static bool IfUseUnitKind(const DepNode &depNode, uint32 index); void UpdateReadyList(DepNode &targetNode, MapleVector &readyList, bool updateEStart) override; - void UpdateScheduleProcessInfo(AArch64ScheduleProcessInfo &info); - void UpdateAdvanceCycle(AArch64ScheduleProcessInfo &scheduleInfo, const DepNode &targetNode); + void UpdateScheduleProcessInfo(AArch64ScheduleProcessInfo &info) const; + void UpdateAdvanceCycle(AArch64ScheduleProcessInfo &scheduleInfo, const DepNode &targetNode) const; bool CheckSchedulable(AArch64ScheduleProcessInfo &info) const; void SelectNode(AArch64ScheduleProcessInfo &scheduleInfo); static void DumpDebugInfo(const ScheduleProcessInfo &scheduleInfo); bool CompareDepNode(DepNode &node1, DepNode &node2, AArch64ScheduleProcessInfo &scheduleInfo) const; - void CalculateMaxUnitKindCount(ScheduleProcessInfo &scheduleInfo); + void CalculateMaxUnitKindCount(ScheduleProcessInfo &scheduleInfo) const; void UpdateReleaseRegInfo(AArch64ScheduleProcessInfo &scheduleInfo); std::set CanFreeRegister(const DepNode &node) const; void UpdateLiveRegSet(AArch64ScheduleProcessInfo &scheduleInfo, const DepNode &node); void InitLiveRegSet(AArch64ScheduleProcessInfo &scheduleInfo); - int CalSeriesCycles(const MapleVector &nodes); + int CalSeriesCycles(const MapleVector &nodes) const; CSRResult DoCSR(DepNode &node1, DepNode &node2, AArch64ScheduleProcessInfo &scheduleInfo) const; AArch64Schedule::CSRResult ScheduleCrossCall(const DepNode &node1, const DepNode &node2) const; int intCalleeSaveThreshold = 0; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cfi_generator.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cfi_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..ed7db87634ffc168971b979d29e177bd5fb99b3e --- /dev/null +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cfi_generator.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MAPLEBE_INCLUDE_CG_CFI_GENERATOR_H +#define MAPLEBE_INCLUDE_CG_CFI_GENERATOR_H +#include "cg_phase.h" +#include "cfi.h" +#include "cgfunc.h" +#include "insn.h" +#include "aarch64_insn.h" +#include "aarch64_operand.h" + +namespace maplebe { +class GenCfi { +public: + explicit GenCfi(CGFunc &func) : cg(*func.GetCG()), cgFunc(func) {} + virtual ~GenCfi() = default; + + void Run(); + +protected: + Insn *InsertCFIDefCfaOffset(BB &bb, Insn &insn, int32 &cfiOffset); /* cfiOffset in-out */ + + Insn *FindStackDefInsn(BB &bb) const; + Insn *FinsStackRevertInsn(BB &bb) const; + + /* CFI related routines */ + int64 GetOffsetFromCFA() const + { + return offsetFromCfa; + } + + /* add increment (can be negative) and return the new value */ + int64 AddtoOffsetFromCFA(int64 delta) + { + offsetFromCfa += delta; + return offsetFromCfa; + } + + CG &cg; + CGFunc &cgFunc; + /* SP offset from Call Frame Address */ + int64 offsetFromCfa = 0; + bool useFP = true; + + static constexpr const int32 kOffset8MemPos = 8; + +private: + void GenerateStartDirective(BB &bb); + void GenerateEndDirective(BB &bb); + void GenerateRegisterStateDirective(BB &bb); + virtual void GenerateRegisterSaveDirective(BB &bb, Insn &stackDefInsn) {} + virtual void GenerateRegisterRestoreDirective(BB &bb, Insn &stackRevertInsn) {} + + /* It inserts a start location information for each function in debugging mode */ + void InsertFirstLocation(BB &bb); +}; +} /* namespace maplebe */ +#endif /* MAPLEBE_INCLUDE_CG_CFI_GENERATOR_H */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_irbuilder.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_irbuilder.h index b34201fc8bfd85d6a5aa5f439c14b4f21dafcdeb..441d0c17eae63397b5b6042a93fb8b40ff47728b 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_irbuilder.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cg_irbuilder.h @@ -68,9 +68,15 @@ public: /* create an operand in cgfunc when no mempool is supplied */ ImmOperand &CreateImm(uint32 size, int64 value, MemPool *mp = nullptr); + ImmOperand &CreateImm(uint32 size, int64 value, bool isSigned, MemPool *mp = nullptr); ImmOperand &CreateImm(const MIRSymbol &symbol, int64 offset, int32 relocs, MemPool *mp = nullptr); + OfstOperand &CreateOfst(int64 offset, uint32 size, MemPool *mp = nullptr); MemOperand &CreateMem(uint32 size, MemPool *mp = nullptr); - MemOperand &CreateMem(RegOperand &baseOpnd, int64 offset, uint32 size); + MemOperand &CreateMem(RegOperand &baseOpnd, int64 offset, uint32 size, MemPool *mp = nullptr); + MemOperand &CreateMem(uint32 size, RegOperand &baseOpnd, ImmOperand &ofstOperand, MemPool *mp = nullptr); + MemOperand &CreateMem(uint32 size, RegOperand &baseOpnd, ImmOperand &ofstOperand, const MIRSymbol &symbol, + MemPool *mp = nullptr); + BitShiftOperand &CreateBitShift(BitShiftOperand::ShiftOp op, uint32 amount, uint32 bitLen, MemPool *mp = nullptr); RegOperand &CreateVReg(uint32 size, RegType type, MemPool *mp = nullptr); RegOperand &CreateVReg(regno_t vRegNO, uint32 size, RegType type, MemPool *mp = nullptr); RegOperand &CreatePReg(regno_t pRegNO, uint32 size, RegType type, MemPool *mp = nullptr); diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgbb.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgbb.h index fa2e31f2520440eac1ff68186a380b7f35d55ec5..e8460f6f378d457aaaf2852f7fcede0cedc0eea0 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgbb.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgbb.h @@ -403,7 +403,7 @@ public: Insn *GetLastMachineInsn() { FOR_BB_INSNS_REV(insn, this) { - if (insn->IsMachineInstruction()) { + if (insn->IsMachineInstruction() && !insn->IsPseudo()) { return insn; } } @@ -1118,11 +1118,11 @@ struct BBIdCmp { } }; -class Bfs : public AnalysisResult { +class Bfs { public: Bfs(CGFunc &cgFunc, MemPool &memPool) - : AnalysisResult(&memPool), - cgfunc(&cgFunc), + : cgfunc(&cgFunc), + memPool(&memPool), alloc(&memPool), cycleSuccs(alloc.Adapter()), visitedBBs(alloc.Adapter()), @@ -1139,8 +1139,9 @@ public: void ComputeBlockOrder(); CGFunc *cgfunc; + MemPool *memPool; MapleAllocator alloc; - MapleVector> cycleSuccs; // bb's succs in cycle + MapleVector> cycleSuccs; // bb's succs in cycle MapleVector visitedBBs; MapleVector sortedBBs; }; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgfunc.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgfunc.h index ccd093126a907d88a5d323cc570c4874e08aff71..a77842f57968002e213a9a98aec3a1499470ac76 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgfunc.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/cgfunc.h @@ -177,6 +177,7 @@ public: LmbcFormalParamInfo *GetLmbcFormalParamInfo(uint32 offset); virtual void LmbcGenSaveSpForAlloca() = 0; void RemoveUnreachableBB(); + Insn &BuildLocInsn(int64 fileNum, int64 lineNum, int64 columnNum); void GenerateLoc(StmtNode *stmt, unsigned &lastSrcLoc, unsigned &lastMplLoc); int32 GetFreqFromStmt(uint32 stmtId); void GenerateInstruction(); @@ -222,8 +223,8 @@ public: virtual void SelectCondSpecialCase2(const CondGotoNode &stmt, BaseNode &opnd0) = 0; virtual void SelectGoto(GotoNode &stmt) = 0; virtual void SelectCall(CallNode &callNode) = 0; - virtual void SelectIcall(IcallNode &icallNode, Operand &fptrOpnd) = 0; - virtual void SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) = 0; + virtual void SelectIcall(IcallNode &icallNode) = 0; + virtual void SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) = 0; virtual Operand *SelectIntrinsicOpWithOneParam(IntrinsicopNode &intrinsicopNode, std::string name) = 0; virtual Operand *SelectIntrinsicOpWithNParams(IntrinsicopNode &intrinsicopNode, PrimType retType, const std::string &name) = 0; @@ -241,7 +242,7 @@ public: virtual Operand *SelectCSyncLockTestSet(IntrinsicopNode &intrinsicopNode, PrimType pty) = 0; virtual Operand *SelectCSyncSynchronize(IntrinsicopNode &intrinsicopNode) = 0; virtual Operand *SelectCAtomicLoadN(IntrinsicopNode &intrinsicopNode) = 0; - virtual Operand *SelectCAtomicExchangeN(IntrinsicopNode &intrinsicopNode) = 0; + virtual Operand *SelectCAtomicExchangeN(const IntrinsiccallNode &intrinsiccallNode) = 0; virtual Operand *SelectCReturnAddress(IntrinsicopNode &intrinsicopNode) = 0; virtual void SelectMembar(StmtNode &membar) = 0; virtual void SelectComment(CommentNode &comment) = 0; @@ -258,7 +259,7 @@ public: PrimType finalBitFieldDestType = kPtyInvalid) = 0; virtual Operand *SelectIreadoff(const BaseNode &parent, IreadoffNode &ireadoff) = 0; virtual Operand *SelectIreadfpoff(const BaseNode &parent, IreadFPoffNode &ireadoff) = 0; - virtual Operand *SelectIntConst(const MIRIntConst &intConst) = 0; + virtual Operand *SelectIntConst(const MIRIntConst &intConst, const BaseNode &parent) = 0; virtual Operand *SelectFloatConst(MIRFloatConst &floatConst, const BaseNode &parent) = 0; virtual Operand *SelectDoubleConst(MIRDoubleConst &doubleConst, const BaseNode &parent) = 0; virtual Operand *SelectStrConst(MIRStrConst &strConst) = 0; @@ -422,7 +423,7 @@ public: }; LabelIdx CreateLabel(); - RegOperand *GetVirtualRegisterOperand(regno_t vRegNO) + RegOperand *GetVirtualRegisterOperand(regno_t vRegNO) const { auto it = vRegOperandTable.find(vRegNO); return it == vRegOperandTable.end() ? nullptr : it->second; @@ -608,6 +609,9 @@ public: } MIRSymbol *GetRetRefSymbol(BaseNode &expr); + + void VerifyAllInsn(); + void GenerateCfiPrologEpilog(); void PatchLongBranch(); @@ -678,7 +682,7 @@ public: debugInfo = dbgInfo; } - void AddDIESymbolLocation(const MIRSymbol *sym, SymbolAlloc *loc); + void AddDIESymbolLocation(const MIRSymbol *sym, SymbolAlloc *loc, bool isParam); virtual void DBGFixCallFrameLocationOffsets() {}; @@ -1395,9 +1399,9 @@ public: return (mirModule.GetSrcLang() != kSrcLangC) || mirModule.IsWithDbgInfo(); } - MapleVector &GetDbgCallFrameLocations() + MapleVector &GetDbgCallFrameLocations(bool isParam) { - return dbgCallFrameLocations; + return isParam ? dbgParamCallFrameLocations : dbgLocalCallFrameLocations; } bool HasAsm() const @@ -1493,6 +1497,15 @@ public: return funcEmitInfo; } + void SetExitBBLost(bool val) + { + exitBBLost = val; + } + bool GetExitBBLost() + { + return exitBBLost; + } + protected: uint32 firstMapleIrVRegNO = 200; /* positioned after physical regs */ uint32 firstNonPregVRegNO; @@ -1531,7 +1544,8 @@ protected: bool hasTakenLabel = false; uint32 frequency = 0; DebugInfo *debugInfo = nullptr; /* debugging info */ - MapleVector dbgCallFrameLocations; + MapleVector dbgParamCallFrameLocations; + MapleVector dbgLocalCallFrameLocations; RegOperand *aggParamReg = nullptr; ReachingDefinition *reachingDef = nullptr; @@ -1612,6 +1626,48 @@ protected: return false; } + PrimType GetPrimTypeFromSize(uint32 byteSize, PrimType defaultType) const + { + constexpr uint32 oneByte = 1; + constexpr uint32 twoByte = 2; + constexpr uint32 fourByte = 4; + switch (byteSize) { + case oneByte: + return PTY_i8; + case twoByte: + return PTY_i16; + case fourByte: + return PTY_i32; + default: + return defaultType; + } + } + + BB *CreateAtomicBuiltinBB() + { + LabelIdx atomicBBLabIdx = CreateLabel(); + BB *atomicBB = CreateNewBB(); + atomicBB->SetKind(BB::kBBIf); + atomicBB->SetAtomicBuiltIn(); + atomicBB->AddLabel(atomicBBLabIdx); + SetLab2BBMap(atomicBBLabIdx, *atomicBB); + GetCurBB()->AppendBB(*atomicBB); + return atomicBB; + } + + // clone old mem and add offset + // oldMem: [base, imm:12] -> newMem: [base, imm:(12 + offset)] + MemOperand &GetMemOperandAddOffset(const MemOperand &oldMem, uint32 offset, uint32 newSize) + { + auto &newMem = static_cast(*oldMem.Clone(*GetMemoryPool())); + auto &oldOffset = *oldMem.GetOffsetOperand(); + auto &newOffst = static_cast(*oldOffset.Clone(*GetMemoryPool())); + newOffst.SetValue(oldOffset.GetValue() + offset); + newMem.SetOffsetOperand(newOffst); + newMem.SetSize(newSize); + return newMem; + } + private: CGFunc &operator=(const CGFunc &cgFunc); CGFunc(const CGFunc &); @@ -1669,6 +1725,9 @@ private: /* save stack protect kinds which can trigger stack protect */ uint8 stackProtectInfo = 0; + + // mark exitBB is unreachable + bool exitBBLost = false; }; /* class CGFunc */ MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgLayoutFrame, maplebe::CGFunc) @@ -1677,6 +1736,8 @@ MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgHandleFunction, maplebe::CGFunc) MAPLE_FUNC_PHASE_DECLARE_END MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgFixCFLocOsft, maplebe::CGFunc) MAPLE_FUNC_PHASE_DECLARE_END +MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgVerify, maplebe::CGFunc) +MAPLE_FUNC_PHASE_DECLARE_END MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgGenCfi, maplebe::CGFunc) MAPLE_FUNC_PHASE_DECLARE_END MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgEmission, maplebe::CGFunc) diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/deps.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/deps.h index 2336eabc8d83a2d1cae529bd7fd1560d044a906c..0deceebf9e46ddaac79b51afdec36e897ffab6a8 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/deps.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/deps.h @@ -16,36 +16,50 @@ #ifndef MAPLEBE_INCLUDE_CG_DEPS_H #define MAPLEBE_INCLUDE_CG_DEPS_H +#include #include "mad.h" +#ifndef ONLY_C #include "pressure.h" -#include +#endif +#include "cgfunc.h" namespace maplebe { -#define PRINT_STR_VAL(STR, VAL) LogInfo::MapleLogger() << std::left << std::setw(12) << STR << VAL << " | "; -#define PRINT_VAL(VAL) LogInfo::MapleLogger() << std::left << std::setw(12) << VAL << " | "; - +#define PRINT_STR_VAL(STR, VAL) (LogInfo::MapleLogger() << std::left << std::setw(12) << (STR) << (VAL) << " | ") +#define PRINT_VAL(VAL) (LogInfo::MapleLogger() << std::left << std::setw(12) << (VAL) << " | ") enum DepType : uint8 { kDependenceTypeTrue, kDependenceTypeOutput, kDependenceTypeAnti, kDependenceTypeControl, + kDependenceTypeMemAccess, // for dependencies between insns of def-use memory operations (alternative true + // dependency) kDependenceTypeMembar, - kDependenceTypeThrow, + kDependenceTypeThrow, // using in java kDependenceTypeSeparator, kDependenceTypeNone }; inline const std::array kDepTypeName = { - "true-dep", "output-dep", "anti-dep", "control-dep", "membar-dep", "throw-dep", "separator-dep", "none-dep", + "true-dep", "output-dep", "anti-dep", "control-dep", "memaccess-dep", + "membar-dep", "throw-dep", "separator-dep", "none-dep", }; enum NodeType : uint8 { kNodeTypeNormal, kNodeTypeSeparator, kNodeTypeEmpty }; enum ScheduleState : uint8 { kNormal, + kCandidate, + kWaiting, kReady, kScheduled, }; +enum SimulateState : uint8 { + kStateUndef, + kRunning, // the instruction is running + kRetired, // the instruction is executed and returns result + kUndefined, +}; + class DepNode; class DepLink { @@ -85,12 +99,9 @@ private: uint32 latency; }; +class RegPressure; class DepNode { public: - bool CanBeScheduled() const; - void OccupyUnits(); - uint32 GetUnitKind() const; - DepNode(Insn &insn, MapleAllocator &alloc) : insn(&insn), units(nullptr), @@ -107,6 +118,7 @@ public: bruteForceSchedCycle(0), validPredsSize(0), validSuccsSize(0), + topoPredsSize(0), preds(alloc.Adapter()), succs(alloc.Adapter()), comments(alloc.Adapter()), @@ -135,6 +147,7 @@ public: bruteForceSchedCycle(0), validPredsSize(0), validSuccsSize(0), + topoPredsSize(0), preds(alloc.Adapter()), succs(alloc.Adapter()), comments(alloc.Adapter()), @@ -149,6 +162,112 @@ public: virtual ~DepNode() = default; + /* If the cpu units required by the reservation type of the instruction are + * idle, return true. + */ + bool IsResourceIdle() const + { + // The 'i' indicates cpu cycles, that 0 indicates the current cycle + uint32 cycles = reservation->GetUnitNum(); + Unit *const *requiredUnits = reservation->GetUnit(); + for (uint32 i = 0; i < cycles; ++i) { + Unit *unit = requiredUnits[i]; + if (unit != nullptr) { + if (!unit->IsIdle(i)) { + return false; + } + } + } + return true; + } + + /* When an instruction is issued, occupy all units required in the specific + * cycle + */ + void OccupyRequiredUnits() const + { + // The 'i' indicates cpu cycles, that 0 indicates the current cycle + uint32 cycles = reservation->GetUnitNum(); + Unit *const *requiredUnits = reservation->GetUnit(); + for (uint32 i = 0; i < cycles; ++i) { + Unit *unit = requiredUnits[i]; + if (unit != nullptr) { + unit->Occupy(i); + } + } + } + + /* Get unit kind of this node's units[0] */ + uint32 GetUnitKind() const + { + uint32 retValue = 0; + if ((units == nullptr) || (units[0] == nullptr)) { + return retValue; + } + + switch (units[0]->GetUnitId()) { + case kUnitIdSlotD: + retValue |= kUnitKindSlot0; + break; + case kUnitIdAgen: + case kUnitIdSlotSAgen: + retValue |= kUnitKindAgen; + break; + case kUnitIdSlotDAgen: + retValue |= kUnitKindAgen; + retValue |= kUnitKindSlot0; + break; + case kUnitIdHazard: + case kUnitIdSlotSHazard: + retValue |= kUnitKindHazard; + break; + case kUnitIdCrypto: + retValue |= kUnitKindCrypto; + break; + case kUnitIdMul: + case kUnitIdSlotSMul: + retValue |= kUnitKindMul; + break; + case kUnitIdDiv: + retValue |= kUnitKindDiv; + break; + case kUnitIdBranch: + case kUnitIdSlotSBranch: + retValue |= kUnitKindBranch; + break; + case kUnitIdStAgu: + retValue |= kUnitKindStAgu; + break; + case kUnitIdLdAgu: + retValue |= kUnitKindLdAgu; + break; + case kUnitIdFpAluS: + case kUnitIdFpAluD: + retValue |= kUnitKindFpAlu; + break; + case kUnitIdFpMulS: + case kUnitIdFpMulD: + retValue |= kUnitKindFpMul; + break; + case kUnitIdFpDivS: + case kUnitIdFpDivD: + retValue |= kUnitKindFpDiv; + break; + case kUnitIdSlot0LdAgu: + retValue |= kUnitKindSlot0; + retValue |= kUnitKindLdAgu; + break; + case kUnitIdSlot0StAgu: + retValue |= kUnitKindSlot0; + retValue |= kUnitKindStAgu; + break; + default: + break; + } + + return retValue; + } + Insn *GetInsn() const { return insn; @@ -163,7 +282,7 @@ public: } const Unit *GetUnitByIndex(uint32 idx) const { - DEBUG_ASSERT(index < unitNum, "out of units"); + DEBUG_ASSERT(idx < unitNum, "out of units"); return units[idx]; } Reservation *GetReservation() const @@ -198,6 +317,14 @@ public: { lStart = start; } + uint32 GetDelay() const + { + return delay; + } + void SetDelay(uint32 prio) + { + delay = prio; + } uint32 GetVisit() const { return visit; @@ -266,7 +393,7 @@ public: { return validPredsSize; } - void DescreaseValidPredsSize() + void DecreaseValidPredsSize() { --validPredsSize; } @@ -282,10 +409,38 @@ public: { validSuccsSize = size; } + void DecreaseValidSuccsSize() + { + --validSuccsSize; + } + uint32 GetTopoPredsSize() + { + return topoPredsSize; + } + void SetTopoPredsSize(uint32 size) + { + topoPredsSize = size; + } + void IncreaseTopoPredsSize() + { + ++topoPredsSize; + } + void DecreaseTopoPredsSize() + { + --topoPredsSize; + } const MapleVector &GetPreds() const { return preds; } + MapleVector::iterator GetPredsBegin() + { + return preds.begin(); + } + MapleVector::iterator GetPredsEnd() + { + return preds.end(); + } void ReservePreds(size_t size) { preds.reserve(size); @@ -298,10 +453,29 @@ public: { preds.pop_back(); } + /* For mock data dependency graph, do not use in normal process */ + void ErasePred(const DepLink &predLink) + { + for (auto iter = preds.begin(); iter != preds.end(); ++iter) { + DepNode &predNode = (*iter)->GetFrom(); + if (predNode.GetInsn()->GetId() == predLink.GetFrom().GetInsn()->GetId()) { + (void)preds.erase(iter); + return; + } + } + } const MapleVector &GetSuccs() const { return succs; } + MapleVector::iterator GetSuccsBegin() + { + return succs.begin(); + } + MapleVector::iterator GetSuccsEnd() + { + return succs.end(); + } void ReserveSuccs(size_t size) { succs.reserve(size); @@ -314,6 +488,11 @@ public: { succs.pop_back(); } + /* For mock data dependency graph */ + MapleVector::iterator EraseSucc(const MapleVector::iterator iter) + { + return succs.erase(iter); + } const MapleVector &GetComments() const { return comments; @@ -322,9 +501,9 @@ public: { comments = com; } - void AddComments(Insn &insn) + void AddComments(Insn &addInsn) { - comments.emplace_back(&insn); + comments.emplace_back(&addInsn); } void ClearComments() { @@ -338,9 +517,9 @@ public: { cfiInsns = insns; } - void AddCfiInsn(Insn &insn) + void AddCfiInsn(Insn &curInsn) { - cfiInsns.emplace_back(&insn); + (void)cfiInsns.emplace_back(&curInsn); } void ClearCfiInsns() { @@ -354,9 +533,9 @@ public: { clinitInsns = insns; } - void AddClinitInsn(Insn &insn) + void AddClinitInsn(Insn &addInsn) { - clinitInsns.emplace_back(&insn); + (void)clinitInsns.emplace_back(&addInsn); } const RegPressure *GetRegPressure() const { @@ -374,116 +553,179 @@ public: } void InitPressure() const { +#ifndef ONLY_C regPressure->InitPressure(); +#endif } +#ifndef ONLY_C const MapleVector &GetPressure() const { return regPressure->GetPressure(); } +#endif void IncPressureByIndex(int32 idx) const { +#ifndef ONLY_C regPressure->IncPressureByIndex(static_cast(idx)); +#endif } void DecPressureByIndex(int32 idx) const { +#ifndef ONLY_C regPressure->DecPressureByIndex(static_cast(idx)); +#endif } - +#ifndef ONLY_C const MapleVector &GetDeadDefNum() const { return regPressure->GetDeadDefNum(); } +#endif void IncDeadDefByIndex(int32 idx) const { +#ifndef ONLY_C regPressure->IncDeadDefByIndex(static_cast(idx)); +#endif } void SetRegUses(RegList ®List) const { +#ifndef ONLY_C regPressure->SetRegUses(®List); +#endif } void SetRegDefs(size_t idx, RegList *regList) const { +#ifndef ONLY_C regPressure->SetRegDefs(idx, regList); +#endif } - int32 GetIncPressure() const + bool GetIncPressure() const { +#ifndef ONLY_C return regPressure->GetIncPressure(); +#else + return false; +#endif } void SetIncPressure(bool value) const { +#ifndef ONLY_C regPressure->SetIncPressure(value); +#endif } int32 GetMaxDepth() const { +#ifndef ONLY_C return regPressure->GetMaxDepth(); +#else + return 0; +#endif } void SetMaxDepth(int32 value) const { +#ifndef ONLY_C regPressure->SetMaxDepth(value); +#endif } int32 GetNear() const { +#ifndef ONLY_C return regPressure->GetNear(); +#else + return 0; +#endif } void SetNear(int32 value) const { +#ifndef ONLY_C regPressure->SetNear(value); +#endif } int32 GetPriority() const { +#ifndef ONLY_C return regPressure->GetPriority(); +#else + return 0; +#endif } void SetPriority(int32 value) const { +#ifndef ONLY_C regPressure->SetPriority(value); +#endif } RegList *GetRegUses(size_t idx) const { +#ifndef ONLY_C return regPressure->GetRegUses(idx); +#else + return nullptr; +#endif } void InitRegUsesSize(size_t size) const { +#ifndef ONLY_C regPressure->InitRegUsesSize(size); +#endif } RegList *GetRegDefs(size_t idx) const { +#ifndef ONLY_C return regPressure->GetRegDefs(idx); +#else + return nullptr; +#endif } void InitRegDefsSize(size_t size) const { +#ifndef ONLY_C regPressure->InitRegDefsSize(size); +#endif } void SetNumCall(int32 value) const { +#ifndef ONLY_C regPressure->SetNumCall(value); +#endif } int32 GetNumCall() const { +#ifndef ONLY_C return regPressure->GetNumCall(); +#else + return 0; +#endif } void SetHasNativeCallRegister(bool value) const { +#ifndef ONLY_C regPressure->SetHasNativeCallRegister(value); +#endif } bool GetHasNativeCallRegister() const { +#ifndef ONLY_C return regPressure->GetHasNativeCallRegister(); +#else + return false; +#endif } const Insn *GetLocInsn() const { return locInsn; } - void SetLocInsn(const Insn &insn) + void SetLocInsn(const Insn &locationInsn) { - locInsn = &insn; + locInsn = &locationInsn; } /* printf dep-node's information of scheduling */ @@ -513,12 +755,18 @@ public: void SetHasPreg(bool value) const { +#ifndef ONLY_C regPressure->SetHasPreg(value); +#endif } bool GetHasPreg() const { +#ifndef ONLY_C return regPressure->GetHasPreg(); +#else + return false; +#endif } void AddUseReg(regno_t reg) @@ -541,6 +789,26 @@ public: return defRegnos; } + void SetSimulateState(SimulateState simulateState) + { + simuState = simulateState; + } + + SimulateState GetSimulateState() const + { + return simuState; + } + + void SetSimulateIssueCycle(uint32 cycle) + { + simulateIssueCycle = cycle; + } + + uint32 GetSimulateIssueCycle() const + { + return simulateIssueCycle; + } + private: Insn *insn; Unit *const *units; @@ -548,6 +816,7 @@ private: uint32 unitNum; uint32 eStart; uint32 lStart; + uint32 delay = 0; // Identify the critical path priority uint32 visit; NodeType type; ScheduleState state; @@ -560,6 +829,9 @@ private: uint32 validPredsSize; uint32 validSuccsSize; + /* For compute eStart by topological order */ + uint32 topoPredsSize; + /* Dependence links. */ MapleVector preds; MapleVector succs; @@ -581,6 +853,8 @@ private: /* For register pressure analysis */ RegPressure *regPressure; + SimulateState simuState = kUndefined; // For calculating original cycles of BB + uint32 simulateIssueCycle = 0; // For calculating original cycles of BB, record the cycle when the insn issuing }; } /* namespace maplebe */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/insn.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/insn.h index cac7520997d6246c3d844d706625d132bcb41d43..7ef3ced44d883a34dc8ba8d192b68aa2acd526fb 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/insn.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/insn.h @@ -23,13 +23,14 @@ /* Maple CG headers */ #include "operand.h" #include "isa.h" -#include "stackmap.h" -#include "mpl_logging.h" -#include "sparse_datainfo.h" - +#include "common_utils.h" /* Maple IR header */ #include "types_def.h" /* for uint32 */ -#include "common_utils.h" +/* Maple Util headers */ +#include "mpl_logging.h" + +#include "stackmap.h" +#include "sparse_datainfo.h" /* Maple Util headers */ #include "mem_reference_table.h" /* for alias */ @@ -40,6 +41,9 @@ class CG; class Emitter; class DepNode; struct InsnDesc; +class InsnBuilder; +class OperandBuilder; + class Insn { public: /* MCC_DecRefResetPair clear 2 stack position, MCC_ClearLocalStackRef clear 1 stack position */ @@ -155,7 +159,7 @@ public: opnds[index] = &opnd; } - // Get size info from machine description + /* Get size info from machine description */ uint32 GetOperandSize(uint32 index) const { CHECK_FATAL(index < opnds.size(), "index out of range!"); @@ -175,6 +179,15 @@ public: return retSize; } + // Insn Function: check legitimacy of opnds. + bool VerifySelf() const + { + if (this->IsCfiInsn() || this->IsDbgInsn()) { + return true; + } + return md->Verify(opnds); + } + void SplitSelf(bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) { md->Split(this, isAfterRegAlloc, insnBuilder, opndBuilder); @@ -317,11 +330,26 @@ public: isFrameDef = b; } + bool IsStackDef() const + { + return isStackDef; + } + void SetStackDef(bool flag) { isStackDef = flag; } + bool IsStackRevert() const + { + return isStackRevert; + } + + void SetStackRevert(bool flag) + { + isStackRevert = flag; + } + bool IsAsmDefCondCode() const { return asmDefCondCode; @@ -764,7 +792,7 @@ private: uint32 id = 0; uint32 address = 0; uint32 nopNum = 0; - uint32 retSize = 0; /* Byte size of the return value if insn is a call. */ + uint32 retSize = 0; /* Byte size of the return value if insn is a call. */ /* record the stack cleared by MCC_ClearLocalStackRef or MCC_DecRefResetPair */ int64 clearStackOffset[kMaxStackOffsetSize] = {-1, -1}; DepNode *depNode = nullptr; /* For dependence analysis, pointing to a dependence node. */ @@ -775,7 +803,8 @@ private: bool isSpill = false; /* used as hint for optimization */ bool isReload = false; /* used as hint for optimization */ bool isFrameDef = false; - bool isStackDef = false; // def sp in prolog + bool isStackDef = false; // def sp in prolog + bool isStackRevert = false; // revert sp in epilog bool asmDefCondCode = false; bool asmModMem = false; bool needSplit = false; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/isa.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/isa.h index b1e3d1f187fc472515344ecc23a601e2132a085b..85d19d1bda73b54c9f6e1c9e5c6d6ca9c8a8a6ef 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/isa.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/isa.h @@ -21,6 +21,8 @@ #include "operand.h" namespace maplebe { +// For verify & split insn +#define VERIFY_INSN(INSN) (INSN)->VerifySelf() #define SPLIT_INSN(INSN, FUNC) \ (INSN)->SplitSelf((FUNC)->IsAfterRegAlloc(), (FUNC)->GetInsnBuilder(), (FUNC)->GetOpndBuilder()) @@ -62,6 +64,7 @@ enum MopProperty : maple::uint8 { kInsnSpecialIntrisic, kInsnIsNop, kInsnIntrinsic, + kInsnIsBreakPoint, }; using regno_t = uint32_t; #define ISABSTRACT 1ULL @@ -96,6 +99,7 @@ using regno_t = uint32_t; #define SPINTRINSIC (1ULL << kInsnSpecialIntrisic) #define ISNOP (1ULL << kInsnIsNop) #define ISINTRINSIC (1ULL << kInsnIntrinsic) +#define ISBREAKPOINT (1ULL << kInsnIsBreakPoint) constexpr maplebe::regno_t kInvalidRegNO = 0; /* @@ -110,8 +114,8 @@ using CsrBitset = uint64_t; template class ConstraintFunction { public: - using cfPointer = bool (*)(ParaType); - bool CheckConstraint(cfPointer ccfunc, ParaType a) const + using CfPointer = bool (*)(ParaType); + bool CheckConstraint(CfPointer ccfunc, ParaType a) const { return (*ccfunc)(a); } @@ -184,6 +188,7 @@ enum EncodeType : uint8 { }; struct InsnDesc { + using ImmValidFunc = std::function)>; using SplitFunc = std::function; InsnDesc(MOperator op, std::vector opndmd, uint64 props, uint64 ltype, const std::string &inName, @@ -198,7 +203,7 @@ struct InsnDesc { // for hard-coded machine description. InsnDesc(MOperator op, std::vector opndmd, uint64 props, uint64 ltype, const std::string &inName, - const std::string &inFormat, uint32 anum, std::function vFunc) + const std::string &inFormat, uint32 anum, const ImmValidFunc &vFunc, const SplitFunc &sFunc) : opc(op), opndMD(opndmd), properties(props), @@ -206,11 +211,28 @@ struct InsnDesc { name(inName), format(inFormat), atomicNum(anum), - validFunc(vFunc) {}; + validFunc(vFunc), + splitFunc(sFunc) {}; + + // for hard-coded machine description. + InsnDesc(MOperator op, std::vector opndmd, uint64 props, uint64 ltype, const std::string &inName, + const std::string &inFormat, uint32 anum, const ImmValidFunc &vFunc, const SplitFunc &sFunc, + EncodeType type, uint32 encode) + : opc(op), + opndMD(opndmd), + properties(props), + latencyType(ltype), + name(inName), + format(inFormat), + atomicNum(anum), + validFunc(vFunc), + splitFunc(sFunc), + encodeType(type), + mopEncode(encode) {}; // for aarch64 assemble InsnDesc(MOperator op, std::vector opndmd, uint64 props, uint64 ltype, const std::string &inName, - const std::string &inFormat, uint32 anum, std::function vFunc, EncodeType type, uint32 encode) + const std::string &inFormat, uint32 anum, const ImmValidFunc &vFunc, EncodeType type, uint32 encode) : opc(op), opndMD(opndmd), properties(props), @@ -241,8 +263,8 @@ struct InsnDesc { uint32 latencyType; const std::string name; const std::string format; - uint32 atomicNum; /* indicate how many asm instructions it will emit. */ - std::function validFunc = nullptr; /* If insn has immOperand, this function needs to be implemented. */ + uint32 atomicNum; /* indicate how many asm instructions it will emit. */ + ImmValidFunc validFunc = nullptr; /* If insn has immOperand, this function needs to be implemented. */ // If insn needs to be split, this function needs to be implemented. SplitFunc splitFunc = nullptr; EncodeType encodeType = kUnknownEncodeType; @@ -384,6 +406,17 @@ struct InsnDesc { return opc; } + bool Verify(const MapleVector &opnds) const + { + if (!validFunc) { + return true; + } + if (opnds.size() != opndMD.size()) { + CHECK_FATAL_FALSE("The size of opnds is wrong."); + } + return validFunc(opnds); + } + void Split(Insn *insn, bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder) const { if (!splitFunc) { @@ -417,14 +450,6 @@ struct InsnDesc { return GetOperandSize() == k64BitSize; } - bool IsValidImmOpnd(int64 val) const - { - if (!validFunc) { - return true; - } - return validFunc(val); - } - uint32 GetLatencyType() const { return latencyType; @@ -455,6 +480,11 @@ struct InsnDesc { return atomicNum; } + bool IsBreakPoint() const + { + return (properties & ISBREAKPOINT) != 0; + } + EncodeType GetEncodeType() const { return encodeType; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/isel.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/isel.h index f12b9f1994b02caf930dad07e89ba59e56df2f22..18023070ff49066ea43ceeace11e9eb2985bc847 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/isel.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/isel.h @@ -78,8 +78,8 @@ public: virtual void SelectRangeGoto(RangeGotoNode &rangeGotoNode, Operand &srcOpnd) = 0; virtual void SelectIgoto(Operand &opnd0) = 0; virtual void SelectCall(CallNode &callNode) = 0; - virtual void SelectIcall(IcallNode &icallNode, Operand &opnd0) = 0; - virtual void SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) = 0; + virtual void SelectIcall(IcallNode &icallNode) = 0; + virtual void SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) = 0; virtual Operand *SelectBswap(IntrinsicopNode &node, Operand &opnd0, const BaseNode &parent) = 0; virtual Operand *SelectFloatingConst(MIRConst &floatingConst, PrimType primType) const = 0; virtual Operand *SelectAddrof(AddrofNode &expr, const BaseNode &parent) = 0; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/memlayout.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/memlayout.h index 2c1e2f10269b38337d2f801fb4c0bbe2e84e351e..377777ca303af3a1f805c441484751f418c66d1c 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/memlayout.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/memlayout.h @@ -56,6 +56,8 @@ enum MemSegmentKind : uint8 { /* local (auto) variables */ kMsRefLocals, kMsLocals, + // segment which is accessed rarely + kMsCold, kMsSpillReg, /* * In between kMsLocals and MS_args_to_stackpass, we allocate @@ -188,6 +190,11 @@ public: */ virtual void AssignSpillLocationsToPseudoRegisters() = 0; + virtual int32 GetCalleeSaveBaseLoc() const + { + return 0; + } + SymbolAlloc *GetSymAllocInfo(uint32 stIdx) { DEBUG_ASSERT(stIdx < symAllocTable.size(), "out of symAllocTable's range"); @@ -238,6 +245,11 @@ public: return segArgsRegPassed.GetSize(); } + uint32 GetSizeOfSegCold() const + { + return segCold.GetSize(); + } + BECommon &GetBECommon() { return be; @@ -299,6 +311,7 @@ protected: MemSegment segArgsStkPassed; MemSegment segArgsRegPassed; MemSegment segArgsToStkPass; + MemSegment segCold = MemSegment(kMsCold); MemSegment segSpillReg = MemSegment(kMsSpillReg); MapleVector symAllocTable; /* index is stindex from StIdx */ MapleVector spillLocTable; /* index is preg idx */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/mplad_bypass_define.def b/ecmascript/compiler/codegen/maple/maple_be/include/cg/mplad_bypass_define.def index bc2394e19ee224b9a8f8e8ba1d825e86ed7eb12b..1f6022e410356f00688e9d616404a0ac53ac69eb 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/mplad_bypass_define.def +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/mplad_bypass_define.def @@ -53,36 +53,36 @@ ADDBYPASS(kLtLoad1, kLtAluExtr, 3); ADDBYPASS(kLtLoad1, kLtShift, 3); ADDBYPASS(kLtLoad1, kLtShiftReg, 3); ADDBYPASS(kLtLoad2, kLtAlu, 3); -ADDSTOREBYPASS(kLtAlu, kLtStore1, 0); -ADDSTOREBYPASS(kLtAlu, kLtStore2, 0); -ADDSTOREBYPASS(kLtAlu, kLtStore3plus, 0); -ADDSTOREBYPASS(kLtAluShift, kLtStore1, 0); -ADDSTOREBYPASS(kLtAluShift, kLtStore2, 0); -ADDSTOREBYPASS(kLtAluShift, kLtStore3plus, 0); -ADDSTOREBYPASS(kLtAluShiftReg, kLtStore1, 0); -ADDSTOREBYPASS(kLtAluShiftReg, kLtStore2, 0); -ADDSTOREBYPASS(kLtAluShiftReg, kLtStore3plus, 0); -ADDSTOREBYPASS(kLtAluExtr, kLtStore1, 0); -ADDSTOREBYPASS(kLtAluExtr, kLtStore2, 0); -ADDSTOREBYPASS(kLtAluExtr, kLtStore3plus, 0); -ADDSTOREBYPASS(kLtShift, kLtStore1, 0); -ADDSTOREBYPASS(kLtShift, kLtStore2, 0); -ADDSTOREBYPASS(kLtShift, kLtStore3plus, 0); -ADDSTOREBYPASS(kLtShiftReg, kLtStore1, 0); -ADDSTOREBYPASS(kLtShiftReg, kLtStore2, 0); -ADDSTOREBYPASS(kLtShiftReg, kLtStore3plus, 0); -ADDSTOREBYPASS(kLtMul, kLtStore1, 1); -ADDSTOREBYPASS(kLtMul, kLtStore2, 1); -ADDSTOREBYPASS(kLtMul, kLtStore3plus, 1); -ADDSTOREBYPASS(kLtLoad1, kLtStore1, 1); -ADDSTOREBYPASS(kLtLoad1, kLtStore2, 1); -ADDSTOREBYPASS(kLtLoad1, kLtStore3plus, 1); -ADDSTOREBYPASS(kLtLoad2, kLtStore1, 1); -ADDSTOREBYPASS(kLtLoad2, kLtStore2, 1); -ADDSTOREBYPASS(kLtLoad2, kLtStore3plus, 1); -ADDSTOREBYPASS(kLtLoad3plus, kLtStore1, 1); -ADDSTOREBYPASS(kLtLoad3plus, kLtStore2, 1); -ADDSTOREBYPASS(kLtLoad3plus, kLtStore3plus, 1); +ADDSTOREADDRBYPASS(kLtAlu, kLtStore1, 0); +ADDSTOREADDRBYPASS(kLtAlu, kLtStore2, 0); +ADDSTOREADDRBYPASS(kLtAlu, kLtStore3plus, 0); +ADDSTOREADDRBYPASS(kLtAluShift, kLtStore1, 0); +ADDSTOREADDRBYPASS(kLtAluShift, kLtStore2, 0); +ADDSTOREADDRBYPASS(kLtAluShift, kLtStore3plus, 0); +ADDSTOREADDRBYPASS(kLtAluShiftReg, kLtStore1, 0); +ADDSTOREADDRBYPASS(kLtAluShiftReg, kLtStore2, 0); +ADDSTOREADDRBYPASS(kLtAluShiftReg, kLtStore3plus, 0); +ADDSTOREADDRBYPASS(kLtAluExtr, kLtStore1, 0); +ADDSTOREADDRBYPASS(kLtAluExtr, kLtStore2, 0); +ADDSTOREADDRBYPASS(kLtAluExtr, kLtStore3plus, 0); +ADDSTOREADDRBYPASS(kLtShift, kLtStore1, 0); +ADDSTOREADDRBYPASS(kLtShift, kLtStore2, 0); +ADDSTOREADDRBYPASS(kLtShift, kLtStore3plus, 0); +ADDSTOREADDRBYPASS(kLtShiftReg, kLtStore1, 0); +ADDSTOREADDRBYPASS(kLtShiftReg, kLtStore2, 0); +ADDSTOREADDRBYPASS(kLtShiftReg, kLtStore3plus, 0); +ADDSTOREADDRBYPASS(kLtMul, kLtStore1, 1); +ADDSTOREADDRBYPASS(kLtMul, kLtStore2, 1); +ADDSTOREADDRBYPASS(kLtMul, kLtStore3plus, 1); +ADDSTOREADDRBYPASS(kLtLoad1, kLtStore1, 1); +ADDSTOREADDRBYPASS(kLtLoad1, kLtStore2, 1); +ADDSTOREADDRBYPASS(kLtLoad1, kLtStore3plus, 1); +ADDSTOREADDRBYPASS(kLtLoad2, kLtStore1, 1); +ADDSTOREADDRBYPASS(kLtLoad2, kLtStore2, 1); +ADDSTOREADDRBYPASS(kLtLoad2, kLtStore3plus, 1); +ADDSTOREADDRBYPASS(kLtLoad3plus, kLtStore1, 1); +ADDSTOREADDRBYPASS(kLtLoad3plus, kLtStore2, 1); +ADDSTOREADDRBYPASS(kLtLoad3plus, kLtStore3plus, 1); ADDBYPASS(kLtAlu, kLtR2f, 0); ADDBYPASS(kLtAluShift, kLtR2f, 0); ADDBYPASS(kLtAluShiftReg, kLtR2f, 0); @@ -121,8 +121,8 @@ ADDBYPASS(kLtAluExtr, kLtClinit, 2); ADDBYPASS(kLtMul, kLtClinit, 3); ADDBYPASS(kLtLoad1, kLtClinit, 3); ADDBYPASS(kLtAlu, kLtClinit, 13); -ADDSTOREBYPASS(kLtClinit, kLtStore1, 11); -ADDSTOREBYPASS(kLtClinit, kLtStore3plus, 11); +ADDSTOREADDRBYPASS(kLtClinit, kLtStore1, 11); +ADDSTOREADDRBYPASS(kLtClinit, kLtStore3plus, 11); ADDBYPASS(kLtClinit, kLtR2f, 11); ADDBYPASS(kLtClinit, kLtR2fCvt, 13); ADDBYPASS(kLtShiftReg, kLtAdrpLdr, 1); @@ -132,12 +132,12 @@ ADDBYPASS(kLtAluExtr, kLtAdrpLdr, 2); ADDBYPASS(kLtMul, kLtAdrpLdr, 3); ADDBYPASS(kLtLoad1, kLtAdrpLdr, 3); ADDBYPASS(kLtAdrpLdr, kLtAlu, 5); -ADDSTOREBYPASS(kLtAdrpLdr, kLtStore1, 3); -ADDSTOREBYPASS(kLtAdrpLdr, kLtStore3plus, 3); +ADDSTOREADDRBYPASS(kLtAdrpLdr, kLtStore1, 3); +ADDSTOREADDRBYPASS(kLtAdrpLdr, kLtStore3plus, 3); ADDBYPASS(kLtAdrpLdr, kLtR2f, 3); ADDBYPASS(kLtAdrpLdr, kLtR2fCvt, 5); ADDBYPASS(kLtClinitTail, kLtAlu, 7); -ADDSTOREBYPASS(kLtClinitTail, kLtStore1, 5); -ADDSTOREBYPASS(kLtClinitTail, kLtStore3plus, 5); +ADDSTOREADDRBYPASS(kLtClinitTail, kLtStore1, 5); +ADDSTOREADDRBYPASS(kLtClinitTail, kLtStore3plus, 5); ADDBYPASS(kLtClinitTail, kLtR2f, 5); ADDBYPASS(kLtClinitTail, kLtR2fCvt, 7); diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/operand.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/operand.h index a8495916c2461e798922aa40f930ddff5bedbb68..c557fbd6ea3e3d96cdfceb3fec57f56bc7ce48f9 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/operand.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/operand.h @@ -18,6 +18,7 @@ #include "becommon.h" #include "cg_option.h" +#include "aarch64/aarch64_imm_valid.h" #include "visitor_common.h" /* maple_ir */ @@ -34,8 +35,6 @@ class OpndDesc; class Emitter; class FuncEmitInfo; -bool IsBitSizeImmediate(maple::uint64 val, maple::uint32 bitLen, maple::uint32 nLowerZeroBits); -bool IsBitmaskImmediate(maple::uint64 val, maple::uint32 bitLen); bool IsMoveWidableImmediate(uint64 val, uint32 bitLen); bool BetterUseMOVZ(uint64 val); @@ -504,7 +503,7 @@ protected: * used for EBO(-O1), it can recognize the registers whose use and def are in * different BB. It is true by default. Sometime it should be false such as * when handle intrinsiccall for target - * aarch64(AArch64CGFunc::SelectIntrinCall). + * aarch64(AArch64CGFunc::SelectIntrinsicCall). */ bool isBBLocal = true; uint32 validBitsNum; @@ -578,21 +577,21 @@ public: bool IsInBitSize(uint8 size, uint8 nLowerZeroBits) const { - return maplebe::IsBitSizeImmediate(static_cast(value), size, nLowerZeroBits); + return IsBitSizeImmediate(static_cast(value), size, nLowerZeroBits); } bool IsBitmaskImmediate() const { DEBUG_ASSERT(!IsZero(), " 0 is reserved for bitmask immediate"); DEBUG_ASSERT(!IsAllOnes(), " -1 is reserved for bitmask immediate"); - return maplebe::IsBitmaskImmediate(static_cast(value), static_cast(size)); + return maplebe::aarch64::IsBitmaskImmediate(static_cast(value), static_cast(size)); } bool IsBitmaskImmediate(uint32 destSize) const { DEBUG_ASSERT(!IsZero(), " 0 is reserved for bitmask immediate"); DEBUG_ASSERT(!IsAllOnes(), " -1 is reserved for bitmask immediate"); - return maplebe::IsBitmaskImmediate(static_cast(value), static_cast(destSize)); + return maplebe::aarch64::IsBitmaskImmediate(static_cast(value), static_cast(destSize)); } bool IsSingleInstructionMovable() const @@ -1293,15 +1292,25 @@ public: DEBUG_ASSERT(dSize >= k8BitSize, "error val:dSize"); DEBUG_ASSERT(dSize <= k128BitSize, "error val:dSize"); DEBUG_ASSERT((dSize & (dSize - 1)) == 0, "error val:dSize"); - if (dSize == k8BitSize || addrMode != kAddrModeBOi) { + if (dSize == k8BitSize) { return false; } OfstOperand *ofstOpnd = GetOffsetImmediate(); - if (ofstOpnd->GetOffsetValue() >= kNegative256BitSize && ofstOpnd->GetOffsetValue() < k256BitSizeInt) { + if (!ofstOpnd) { return false; } - return ((static_cast(ofstOpnd->GetOffsetValue()) & - static_cast((1U << static_cast(GetImmediateOffsetAlignment(dSize))) - 1)) != 0); + int64 ofstVal = ofstOpnd->GetOffsetValue(); + if (addrMode == kAddrModeBOi) { + if (ofstVal >= kMinSimm32 && ofstVal <= kMaxSimm32) { + return false; + } + return ((static_cast(ofstOpnd->GetOffsetValue()) & + static_cast((1U << static_cast(GetImmediateOffsetAlignment(dSize))) - 1)) != 0); + } else if (addrMode == kAddrModeLo12Li) { + uint32 alignByte = (dSize / k8BitSize); + return ((ofstVal % static_cast(alignByte)) != k0BitSize); + } + return false; } static bool IsSIMMOffsetOutOfRange(int64 offset, bool is64bit, bool isLDSTPair) @@ -1491,8 +1500,8 @@ private: class LabelOperand : public OperandVisitable { public: - LabelOperand(const char *parent, LabelIdx labIdx) - : OperandVisitable(kOpdBBAddress, 0), labelIndex(labIdx), parentFunc(parent), orderID(-1u) + LabelOperand(const char *parent, LabelIdx labIdx, MemPool &mp) + : OperandVisitable(kOpdBBAddress, 0), labelIndex(labIdx), parentFunc(parent, &mp), orderID(-1u) { } @@ -1519,7 +1528,7 @@ public: return labelIndex; } - const std::string &GetParentFunc() const + const MapleString &GetParentFunc() const { return parentFunc; } @@ -1568,7 +1577,7 @@ public: protected: LabelIdx labelIndex; - const std::string parentFunc; + const MapleString parentFunc; private: /* this index records the order this label is defined during code emit. */ @@ -1762,6 +1771,11 @@ public: return extendOp; } + uint32 GetValue() const + { + return shiftAmount; + } + bool Less(const Operand &right) const override; void Dump() const override @@ -1832,6 +1846,11 @@ public: return shiftOp; } + uint32 GetValue() const + { + return GetShiftAmount(); + } + void Dump() const override { CHECK_FATAL(false, "dont run here"); diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/schedule.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/schedule.h index 97f71f3ab57c9b39ac2777e7f26e124e28eb9058..9f652cc96ad91660546aefedfe577f507bbca002 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/schedule.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/schedule.h @@ -17,14 +17,131 @@ #define MAPLEBE_INCLUDE_CG_SCHEDULE_H #include "insn.h" +#include "live.h" #include "mad.h" #include "dependence.h" -#include "live.h" namespace maplebe { #define LIST_SCHED_DUMP_NEWPM CG_DEBUG_FUNC(f) #define LIST_SCHED_DUMP_REF CG_DEBUG_FUNC(cgFunc) +class ScheduleProcessInfo { +public: + explicit ScheduleProcessInfo(uint32 size) + { + availableReadyList.reserve(size); + scheduledNodes.reserve(size); + } + + virtual ~ScheduleProcessInfo() = default; + + uint32 GetLastUpdateCycle() const + { + return lastUpdateCycle; + } + + void SetLastUpdateCycle(uint32 updateCycle) + { + lastUpdateCycle = updateCycle; + } + + uint32 GetCurrCycle() const + { + return currCycle; + } + + void IncCurrCycle() + { + ++currCycle; + } + + void DecAdvanceCycle() + { + advanceCycle--; + } + + uint32 GetAdvanceCycle() const + { + return advanceCycle; + } + + void SetAdvanceCycle(uint32 cycle) + { + advanceCycle = cycle; + } + + void ClearAvailableReadyList() + { + availableReadyList.clear(); + } + + void PushElemIntoAvailableReadyList(DepNode *node) + { + availableReadyList.emplace_back(node); + } + + size_t SizeOfAvailableReadyList() const + { + return availableReadyList.size(); + } + + bool AvailableReadyListIsEmpty() const + { + return availableReadyList.empty(); + } + + void SetAvailableReadyList(const std::vector &tempReadyList) + { + availableReadyList = tempReadyList; + } + + const std::vector &GetAvailableReadyList() const + { + return availableReadyList; + } + + const std::vector &GetAvailableReadyList() + { + return availableReadyList; + } + + void PushElemIntoScheduledNodes(DepNode *node) + { + node->SetState(kScheduled); + node->SetSchedCycle(currCycle); + node->OccupyRequiredUnits(); + scheduledNodes.emplace_back(node); + } + + bool IsFirstSeparator() const + { + return isFirstSeparator; + } + + void ResetIsFirstSeparator() + { + isFirstSeparator = false; + } + + size_t SizeOfScheduledNodes() const + { + return scheduledNodes.size(); + } + + const std::vector &GetScheduledNodes() const + { + return scheduledNodes; + } + +private: + std::vector availableReadyList; + std::vector scheduledNodes; + uint32 lastUpdateCycle = 0; + uint32 currCycle = 0; + uint32 advanceCycle = 0; + bool isFirstSeparator = true; +}; + class RegPressureSchedule { public: RegPressureSchedule(CGFunc &func, MapleAllocator &alloc) @@ -38,6 +155,7 @@ public: partialScheduledNode(alloc.Adapter()), optimisticScheduledNodes(alloc.Adapter()), splitterIndexes(alloc.Adapter()), + integerRegisterPressureList(alloc.Adapter()), liveInRegNO(alloc.Adapter()), liveOutRegNO(alloc.Adapter()) { @@ -45,22 +163,22 @@ public: virtual ~RegPressureSchedule() = default; void InitBBInfo(BB &b, MemPool &memPool, const MapleVector &nodes); - void BuildPhyRegInfo(const std::vector ®NumVec); - void initPartialSplitters(const MapleVector &nodes); + void BuildPhyRegInfo(const std::vector ®NumVec) const; + void InitPartialSplitters(const MapleVector &nodes); void Init(const MapleVector &nodes); void UpdateBBPressure(const DepNode &node); - void CalculatePressure(DepNode &node, regno_t reg, bool def); + void CalculatePressure(const DepNode &node, regno_t reg, bool def) const; void SortReadyList(); static bool IsLastUse(const DepNode &node, regno_t regNO); - void ReCalculateDepNodePressure(DepNode &node); + void ReCalculateDepNodePressure(const DepNode &node) const; void UpdateLiveReg(const DepNode &node, regno_t reg, bool def); bool CanSchedule(const DepNode &node) const; void UpdateReadyList(const DepNode &node); void BruteUpdateReadyList(const DepNode &node, std::vector &changedToReady); void RestoreReadyList(DepNode &node, std::vector &changedToReady); void UpdatePriority(DepNode &node); - void CalculateMaxDepth(const MapleVector &nodes); - void CalculateNear(const DepNode &node); + void CalculateMaxDepth(const MapleVector &nodes) const; + void CalculateNear(const DepNode &node) const; static bool DepNodePriorityCmp(const DepNode *node1, const DepNode *node2); DepNode *ChooseNode(); void DoScheduling(MapleVector &nodes); @@ -101,7 +219,7 @@ private: /* save split points */ MapleVector splitterIndexes; /* save integer register pressure */ - std::vector integerRegisterPressureList; + MapleVector integerRegisterPressureList; /* save the amount of every type register. */ int32 *physicalRegNum = nullptr; int32 maxPriority = 0; diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/standardize.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/standardize.h index 7b3aea275b92ebebd193c9bd0c9c582dd069cf43..e613f75d6b735ea562c3c439fa673eeb2a6e689d 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/standardize.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/standardize.h @@ -66,5 +66,7 @@ private: CGFunc *cgFunc; bool needAddrMapping = false; }; +MAPLE_FUNC_PHASE_DECLARE_BEGIN(InstructionStandardize, maplebe::CGFunc) +MAPLE_FUNC_PHASE_DECLARE_END } // namespace maplebe #endif /* MAPLEBE_INCLUDE_STANDARDIZE_H */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_MPISel.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_MPISel.h index 520e7d0b9a2d6904c5f30d862f9c4c71980ef256..e98a848ce611d3b16ef3744a92b473bf72c2a646 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_MPISel.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_MPISel.h @@ -27,7 +27,7 @@ public: void SelectReturn(NaryStmtNode &retNode, Operand &opnd) override; void SelectReturn() override; void SelectCall(CallNode &callNode) override; - void SelectIcall(IcallNode &icallNode, Operand &opnd0) override; + void SelectIcall(IcallNode &icallNode) override; Operand &ProcessReturnReg(PrimType primType, int32 sReg) override; Operand &GetTargetRetOperand(PrimType primType, int32 sReg) override; Operand *SelectAddrof(AddrofNode &expr, const BaseNode &parent) override; @@ -35,7 +35,7 @@ public: Operand *SelectAddrofLabel(AddroflabelNode &expr, const BaseNode &parent) override; Operand *SelectFloatingConst(MIRConst &floatingConst, PrimType primType) const override; void SelectGoto(GotoNode &stmt) override; - void SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) override; + void SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) override; void SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd, Operand &opndRhs) override; void SelectAggDassign(maplebe::MirTypeInfo &lhsInfo, MemOperand &symbolMem, Operand &opndRhs) override; void SelectAggCopy(MemOperand &lhs, MemOperand &rhs, uint32 copySize) override; @@ -78,7 +78,7 @@ private: /* lt/le in float is replaced by gt/ge on swaped operands */ void SelectCmp(Operand &opnd0, Operand &opnd1, PrimType primType, bool isSwap = false); void SelectCmpFloatEq(RegOperand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primResType, - PrimType primOpndType); + PrimType primOpndType); void SelectCmpResult(RegOperand &resOpnd, Opcode opCode, PrimType primType, PrimType primOpndType); void SelectSelect(Operand &resOpnd, Operand &trueOpnd, Operand &falseOpnd, PrimType primType, Opcode cmpOpcode, PrimType cmpPrimType); @@ -91,7 +91,6 @@ private: void CreateCallStructParamPassByReg(MemOperand &memOpnd, regno_t regNo, uint32 parmNum); void CreateCallStructParamPassByStack(MemOperand &addrOpnd, int32 symSize, int32 baseOffset); void SelectAggCopyReturn(const MIRSymbol &symbol, MIRType &symbolType, uint64 symbolSize); - uint32 GetAggCopySize(uint32 offset1, uint32 offset2, uint32 alignment) const; bool IsParamStructCopy(const MIRSymbol &symbol); void SelectMinOrMax(bool isMin, Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) override; void SelectLibCall(const std::string &funcName, std::vector &opndVec, PrimType primType, diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_cgfunc.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_cgfunc.h index 7ef95db6163f8bd68c18130557b0f20c6b35a6a5..d3d2c57a0464c8e3e278baf37525caaf2f7c6334 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_cgfunc.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/x86_64/x64_cgfunc.h @@ -70,8 +70,8 @@ public: void SelectCondSpecialCase2(const CondGotoNode &stmt, BaseNode &opnd0) override; void SelectGoto(GotoNode &stmt) override; void SelectCall(CallNode &callNode) override; - void SelectIcall(IcallNode &icallNode, Operand &fptrOpnd) override; - void SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) override; + void SelectIcall(IcallNode &icallNode) override; + void SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) override; Operand *SelectIntrinsicOpWithOneParam(IntrinsicopNode &intrinopNode, std::string name) override; Operand *SelectCclz(IntrinsicopNode &intrinopNode) override; Operand *SelectCctz(IntrinsicopNode &intrinopNode) override; @@ -84,7 +84,7 @@ public: Operand *SelectCSyncFetch(IntrinsicopNode &intrinsicopNode, Opcode op, bool fetchBefore) override; Operand *SelectCSyncSynchronize(IntrinsicopNode &intrinsicopNode) override; Operand *SelectCAtomicLoadN(IntrinsicopNode &intrinsicopNode) override; - Operand *SelectCAtomicExchangeN(IntrinsicopNode &intrinsicopNode) override; + Operand *SelectCAtomicExchangeN(const IntrinsiccallNode &intrinsicopNode) override; Operand *SelectCSyncBoolCmpSwap(IntrinsicopNode &intrinopNode) override; Operand *SelectCSyncValCmpSwap(IntrinsicopNode &intrinopNode) override; Operand *SelectCSyncLockTestSet(IntrinsicopNode &intrinopNode, PrimType pty) override; @@ -102,7 +102,7 @@ public: PrimType finalBitFieldDestType = kPtyInvalid) override; Operand *SelectIreadoff(const BaseNode &parent, IreadoffNode &ireadoff) override; Operand *SelectIreadfpoff(const BaseNode &parent, IreadFPoffNode &ireadoff) override; - Operand *SelectIntConst(const MIRIntConst &intConst) override; + Operand *SelectIntConst(const MIRIntConst &intConst, const BaseNode &parent) override; Operand *SelectFloatConst(MIRFloatConst &floatConst, const BaseNode &parent) override; Operand *SelectDoubleConst(MIRDoubleConst &doubleConst, const BaseNode &parent) override; Operand *SelectStrConst(MIRStrConst &strConst) override; diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/ad/mad.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/ad/mad.cpp index 6771619756c58b99859074a76cb9f95128e12308..0e1069a3fc9fdc8c61ba1d8da4372ca05eff248f 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/ad/mad.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/ad/mad.cpp @@ -15,9 +15,10 @@ #include "mad.h" #include +#include #if TARGAARCH64 #include "aarch64_operand.h" -#elif TARGRISCV64 +#elif defined(TARGRISCV64) && TARGRISCV64 #include "riscv64_operand.h" #endif #include "schedule.h" @@ -29,13 +30,13 @@ const std::string kUnitName[] = { "None", }; /* Unit */ -Unit::Unit(enum UnitId theUnitId) : unitId(theUnitId), unitType(kUnitTypePrimart), occupancyTable(0), compositeUnits() +Unit::Unit(enum UnitId theUnitId) : unitId(theUnitId), unitType(kUnitTypePrimart), occupancyTable(), compositeUnits() { MAD::AddUnit(*this); } Unit::Unit(enum UnitType theUnitType, enum UnitId theUnitId, int numOfUnits, ...) - : unitId(theUnitId), unitType(theUnitType), occupancyTable(0) + : unitId(theUnitId), unitType(theUnitType), occupancyTable() { DEBUG_ASSERT(numOfUnits > 1, "CG internal error, composite unit with less than 2 unit elements."); va_list ap; @@ -56,54 +57,54 @@ std::string Unit::GetName() const return kUnitName[GetUnitId()]; } -/* Check if unit is free at next "cycle" cycle. */ -bool Unit::IsFree(uint32 cycle) const +/* If the unit is idle in the CYCLE, return true */ +bool Unit::IsIdle(uint32 cycle) const { - if (GetUnitType() == kUnitTypeOr) { - for (auto unit : compositeUnits) { - if (unit->IsFree(cycle)) { + if (unitType == kUnitTypeOr) { + // For 'or'-unit, if one of them is idle, return true + for (Unit *unit : compositeUnits) { + if (unit->IsIdle(cycle)) { return true; } } return false; } else if (GetUnitType() == kUnitTypeAnd) { - for (auto unit : compositeUnits) { - if (!unit->IsFree(cycle)) { + // For 'and'-unit, if all of them are idle, return true + for (auto *unit : compositeUnits) { + if (!unit->IsIdle(cycle)) { return false; } } return true; } - if ((occupancyTable & (1u << cycle)) != 0) { - return false; - } - return true; + return ((occupancyTable & std::bitset(1u << cycle)) == 0); } -/* Occupy unit at next "cycle" cycle. */ -void Unit::Occupy(const Insn &insn, uint32 cycle) +/* Occupy unit in the CYCLE */ +void Unit::Occupy(uint32 cycle) { if (GetUnitType() == kUnitTypeOr) { + // For 'or'-unit, occupy the first idle unit for (auto unit : GetCompositeUnits()) { - if (unit->IsFree(cycle)) { - unit->Occupy(insn, cycle); + if (unit->IsIdle(cycle)) { + unit->Occupy(cycle); return; } } - - DEBUG_ASSERT(false, "CG internal error, should not be reach here."); - return; + // If there is no return before, there is an error. + CHECK_FATAL(false, "when the instruction issue, all units it required must be idle"); } else if (GetUnitType() == kUnitTypeAnd) { + // For 'and'-unit, occupy all the unit for (auto unit : GetCompositeUnits()) { - unit->Occupy(insn, cycle); + unit->Occupy(cycle); } return; } - occupancyTable |= (1u << cycle); + occupancyTable |= (1ULL << cycle); } -/* Advance all units one cycle */ -void Unit::AdvanceCycle() +/* Advance one cpu cycle, and update the occupation status of all units */ +void Unit::AdvanceOneCycle() { if (GetUnitType() != kUnitTypePrimart) { return; @@ -139,7 +140,7 @@ void Unit::Dump(int indent) const LogInfo::MapleLogger() << "occupancyTable = " << occupancyTable << '\n'; } -uint32 Unit::GetOccupancyTable() const +std::bitset Unit::GetOccupancyTable() const { return occupancyTable; } @@ -183,7 +184,7 @@ void MAD::InitParallelism() const { #include "mplad_arch_define.def" } -/* according insn's insnType to get a reservation */ +/* Return the reservation by latencyType of the instruction */ Reservation *MAD::FindReservation(const Insn &insn) const { uint32 insnType = insn.GetLatencyType(); @@ -195,7 +196,7 @@ Reservation *MAD::FindReservation(const Insn &insn) const return nullptr; } -/* Get latency that is def insn to use insn */ +/* Return latency from producer instruction to consumer instruction */ int MAD::GetLatency(const Insn &def, const Insn &use) const { int latency = BypassLatency(def, use); @@ -205,7 +206,7 @@ int MAD::GetLatency(const Insn &def, const Insn &use) const return latency; } -/* Get bypass latency that is def insn to use insn */ +/* Return latency according to latency from producer instruction to consumer instruction */ int MAD::BypassLatency(const Insn &def, const Insn &use) const { int latency = -1; @@ -221,17 +222,25 @@ int MAD::BypassLatency(const Insn &def, const Insn &use) const return latency; } -/* Get insn's default latency */ +/* Return default cost of the instruction */ int MAD::DefaultLatency(const Insn &insn) const { Reservation *res = insn.GetDepNode()->GetReservation(); return res != nullptr ? res->GetLatency() : 0; } -void MAD::AdvanceCycle() const +/* In the dual-issue arch, if two slots are occupied in the current cycle, + * return true + */ +bool MAD::IsFullIssued() const +{ + return !GetUnitByUnitId(kUnitIdSlot0)->IsIdle(0) && !GetUnitByUnitId(kUnitIdSlot1)->IsIdle(0); +} + +void MAD::AdvanceOneCycleForAll() const { for (auto unit : allUnits) { - unit->AdvanceCycle(); + unit->AdvanceOneCycle(); } } @@ -242,7 +251,7 @@ void MAD::ReleaseAllUnits() const } } -void MAD::SaveStates(std::vector &occupyTable, int size) const +void MAD::SaveStates(std::vector> &occupyTable, int size) const { int i = 0; for (auto unit : allUnits) { @@ -255,30 +264,14 @@ void MAD::SaveStates(std::vector &occupyTable, int size) const #define ADDBYPASS(DEFLTTY, USELTTY, LT) AddBypass(*(new Bypass(DEFLTTY, USELTTY, LT))) #define ADDALUSHIFTBYPASS(DEFLTTY, USELTTY, LT) AddBypass(*(new AluShiftBypass(DEFLTTY, USELTTY, LT))) #define ADDACCUMULATORBYPASS(DEFLTTY, USELTTY, LT) AddBypass(*(new AccumulatorBypass(DEFLTTY, USELTTY, LT))) -#define ADDSTOREBYPASS(DEFLTTY, USELTTY, LT) AddBypass(*(new StoreBypass(DEFLTTY, USELTTY, LT))) +#define ADDSTOREADDRBYPASS(DEFLTTY, USELTTY, LT) AddBypass(*(new StoreAddrBypass(DEFLTTY, USELTTY, LT))) void MAD::InitBypass() const { #include "mplad_bypass_define.def" } -bool MAD::IsSlot0Free() const -{ - if (GetUnitByUnitId(kUnitIdSlot0)->IsFree(0)) { - return false; - } - return true; -} - -bool MAD::IsFullIssued() const -{ - if (GetUnitByUnitId(kUnitIdSlot0)->IsFree(0) || GetUnitByUnitId(kUnitIdSlot1)->IsFree(0)) { - return false; - } - return true; -} - -void MAD::RestoreStates(std::vector &occupyTable, int size) const +void MAD::RestoreStates(std::vector> &occupyTable, int size) const { int i = 0; for (auto unit : allUnits) { @@ -295,59 +288,119 @@ bool Bypass::CanBypass(const Insn &defInsn, const Insn &useInsn) const return true; } +/* Return true if the USEINSN is an arithmetic or logic or shift instruction, + * and the defOpnd of DEFINSN is not used in shift operation of USEINSN. + * e.g. + * true: r3=r2+x1 -> r5=r4<<0x2+r3 + * false: r3=r2+x1 -> r5=r3<<0x2+r4 + */ bool AluShiftBypass::CanBypass(const Insn &defInsn, const Insn &useInsn) const { - /* - * hook condition - * true: r1=r2+x1 -> r3=r2<<0x2+r1 - * false:r1=r2+x1 -> r3=r1<<0x2+r2 - */ - return &(defInsn.GetOperand(kInsnFirstOpnd)) != &(useInsn.GetOperand(kInsnSecondOpnd)); + RegOperand *productOpnd = nullptr; + uint32 defOpndNum = defInsn.GetOperandSize(); + for (uint32 i = 0; i < defOpndNum; ++i) { + if (defInsn.OpndIsDef(i)) { + Operand &opnd = defInsn.GetOperand(i); + CHECK_FATAL(opnd.IsRegister(), "invalid producer insn of type alu-shift"); + productOpnd = &static_cast(opnd); + break; + } + } + CHECK_NULL_FATAL(productOpnd); + uint32 useOpndNum = useInsn.GetOperandSize(); + if (useOpndNum <= kInsnThirdOpnd) { // operand_size <= 2 + return true; + } + Operand &lastUseOpnd = useInsn.GetOperand(useOpndNum - 1); + if (lastUseOpnd.GetKind() != Operand::kOpdShift && lastUseOpnd.GetKind() == Operand::kOpdExtend && + lastUseOpnd.GetKind() == Operand::kOpdRegShift) { + return true; + } + Operand &shiftOpnd = useInsn.GetOperand(useOpndNum - 2); + if (shiftOpnd.GetKind() != Operand::kOpdRegister) { + return true; + } + if (static_cast(shiftOpnd).GetRegisterNumber() == productOpnd->GetRegisterNumber()) { + return false; + } + return true; } +/* Return true if the defOpnd of DEFINSN is used in the accumulator + * operation(MLA-like) of USEINSN. In aarch64, the MOPs are in {madd, msub, + * fmadd, fmsub, fnmadd, fnmsub} e.g. The USEINSN is {madd|msub} and the defOpnd + * is used in the following cases: true: r98=x0*x1 -> x0=x2*x3+r98 + * false:r98=x0*x1 -> x0=x2*r98+x3 + */ bool AccumulatorBypass::CanBypass(const Insn &defInsn, const Insn &useInsn) const { - /* - * hook condition - * true: r98=x0*x1 -> x0=x2*x3+r98 - * false:r98=x0*x1 -> x0=x2*r98+x3 - */ - return (&(defInsn.GetOperand(kInsnFirstOpnd)) != &(useInsn.GetOperand(kInsnSecondOpnd)) && - &(defInsn.GetOperand(kInsnFirstOpnd)) != &(useInsn.GetOperand(kInsnThirdOpnd))); + RegOperand *productOpnd = nullptr; + uint32 defOpndNum = defInsn.GetOperandSize(); + for (uint32 i = 0; i < defOpndNum; ++i) { + if (defInsn.OpndIsDef(i)) { + Operand &opnd = defInsn.GetOperand(i); + CHECK_FATAL(opnd.IsRegister(), "invalid producer insn of type alu-shift"); + productOpnd = &static_cast(opnd); + break; + } + } + CHECK_NULL_FATAL(productOpnd); + // Currently, the MOPs of valid USEINSN are in {madd, msub, fmadd, fmsub, + // fnmadd, fnmsub}, that have four operands of LATENCYTYPE kLtMul and + // kLtFpmac. + uint32 useOpndNum = useInsn.GetOperandSize(); + if (useOpndNum != kInsnFifthOpnd) { // operand_size != 4 + return false; + } + // Get accumulator operand + Operand &accuOpnd = useInsn.GetOperand(useOpndNum - 1); + CHECK_FATAL(accuOpnd.IsRegister(), "invalid consumer insn of type mul"); + if (static_cast(accuOpnd).GetRegisterNumber() == productOpnd->GetRegisterNumber()) { + return true; + } + return false; } -bool StoreBypass::CanBypass(const Insn &defInsn, const Insn &useInsn) const +/* Return true if the USEINSN(an integer store) does not use the defOpnd of + * DEFINSN to calculate the mem address. e.g. true: r96=r92+x2 -> str r96, [r92] + * false: r96=r92+x2 -> str r92, [r96, #8] + * false: r96=r92+x2 -> str r92, [r94, r96] + */ +bool StoreAddrBypass::CanBypass(const Insn &defInsn, const Insn &useInsn) const { - /* - * hook condition - * true: r96=r92+x2 -> str r96, [r92] - * false:r96=r92+x2 -> str r92, [r96] - * false:r96=r92+x2 -> str r92, [r94, r96] - */ -#if TARGAARCH64 - switch (useInsn.GetMachineOpcode()) { - case MOP_wstrb: - case MOP_wstrh: - case MOP_wstr: - case MOP_xstr: - case MOP_sstr: - case MOP_dstr: { - auto &useMemOpnd = static_cast(useInsn.GetOperand(kInsnSecondOpnd)); - return (&(defInsn.GetOperand(kInsnFirstOpnd)) != useMemOpnd.GetOffset() && - &(defInsn.GetOperand(kInsnFirstOpnd)) != useMemOpnd.GetBaseRegister()); + // Only for LATENCY-TYPE {kLtStore1, kLtStore2, kLtStore3plus} + if (useInsn.GetLatencyType() != kLtStore1 && useInsn.GetLatencyType() != kLtStore2 && + useInsn.GetLatencyType() != kLtStore3plus) { + return false; + } + RegOperand *productOpnd = nullptr; + uint32 defOpndNum = defInsn.GetOperandSize(); + for (uint32 i = 0; i < defOpndNum; ++i) { + if (defInsn.OpndIsDef(i)) { + Operand &opnd = defInsn.GetOperand(i); + CHECK_FATAL(opnd.IsRegister(), "invalid producer insn of type alu-shift"); + productOpnd = &static_cast(opnd); + break; } - case MOP_wstp: - case MOP_xstp: { - auto &useMemOpnd = static_cast(useInsn.GetOperand(kInsnThirdOpnd)); - return (&(defInsn.GetOperand(kInsnFirstOpnd)) != useMemOpnd.GetOffset() && - &(defInsn.GetOperand(kInsnFirstOpnd)) != useMemOpnd.GetBaseRegister()); + } + CHECK_NULL_FATAL(productOpnd); + uint32 useOpndNum = useInsn.GetOperandSize(); + for (uint32 i = 0; i < useOpndNum; ++i) { + Operand &opnd = useInsn.GetOperand(i); + if (opnd.GetKind() == Operand::kOpdMem) { + auto &memOpnd = static_cast(opnd); + RegOperand *baseOpnd = memOpnd.GetBaseRegister(); + RegOperand *indexOpnd = memOpnd.GetIndexRegister(); + if (baseOpnd != nullptr && baseOpnd->GetRegisterNumber() == productOpnd->GetRegisterNumber()) { + return false; + } + if (indexOpnd != nullptr && indexOpnd->GetRegisterNumber() == productOpnd->GetRegisterNumber()) { + return false; + } + break; } - - default: - return false; } -#endif - return false; + return true; } /* Reservation */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/be/lower.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/be/lower.cpp index d524dafd9e284972f3f448119b8fcd0705a0c4e2..dd54ec7f57ec581a1c8f9c5a768881984eadaa79 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/be/lower.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/be/lower.cpp @@ -1052,6 +1052,16 @@ void CGLowerer::LowerAsmStmt(AsmNode *asmNode, BlockNode *newBlk) newBlk->AddStatement(asmNode); } +BaseNode *CGLowerer::NeedRetypeWhenLowerCallAssigned(PrimType pType) +{ + BaseNode *retNode = mirModule.GetMIRBuilder()->CreateExprRegread(pType, -kSregRetval0); + if (IsPrimitiveInteger(pType) && GetPrimTypeBitSize(pType) <= k32BitSize) { + auto newPty = IsPrimitiveUnsigned(pType) ? PTY_u64 : PTY_i64; + retNode = mirModule.GetMIRBuilder()->CreateExprTypeCvt(OP_cvt, newPty, pType, *retNode); + } + return retNode; +} + DassignNode *CGLowerer::SaveReturnValueInLocal(StIdx stIdx, uint16 fieldID) { MIRSymbol *var; @@ -1067,7 +1077,7 @@ DassignNode *CGLowerer::SaveReturnValueInLocal(StIdx stIdx, uint16 fieldID) } else { pType = GlobalTables::GetTypeTable().GetTypeTable().at(var->GetTyIdx())->GetPrimType(); } - RegreadNode *regRead = mirModule.GetMIRBuilder()->CreateExprRegread(pType, -kSregRetval0); + auto *regRead = NeedRetypeWhenLowerCallAssigned(pType); return mirModule.GetMIRBuilder()->CreateStmtDassign(*var, fieldID, regRead); } @@ -1167,22 +1177,27 @@ StmtNode *CGLowerer::GenIntrinsiccallNode(const StmtNode &stmt, PUIdx &funcCalle PUIdx bFunc = GetBuiltinToUse(origCall.GetIntrinsic()); if (bFunc != kFuncNotFound) { newCall = mirModule.GetMIRBuilder()->CreateStmtCall(bFunc, origCall.GetNopnd()); + CHECK_FATAL(newCall->GetOpCode() == OP_call, "intrinsicnode except intrinsiccall is not expected"); } else { if (stmt.GetOpCode() == OP_intrinsiccallassigned) { newCall = mirModule.GetMIRBuilder()->CreateStmtIntrinsicCall(origCall.GetIntrinsic(), origCall.GetNopnd()); + CHECK_FATAL(newCall->GetOpCode() == OP_intrinsiccall, + "intrinsicnode except intrinsiccall is not expected"); } else if (stmt.GetOpCode() == OP_xintrinsiccallassigned) { newCall = mirModule.GetMIRBuilder()->CreateStmtXintrinsicCall(origCall.GetIntrinsic(), origCall.GetNopnd()); + CHECK_FATAL(newCall->GetOpCode() == OP_intrinsiccall, + "intrinsicnode except intrinsiccall is not expected"); } else { newCall = mirModule.GetMIRBuilder()->CreateStmtIntrinsicCall(origCall.GetIntrinsic(), origCall.GetNopnd(), origCall.GetTyIdx()); + CHECK_FATAL(newCall->GetOpCode() == OP_intrinsiccallwithtype, + "intrinsicnode except OP_intrinsiccallwithtype is not expected"); } } newCall->SetSrcPos(stmt.GetSrcPos()); funcCalled = bFunc; - CHECK_FATAL((newCall->GetOpCode() == OP_call || newCall->GetOpCode() == OP_intrinsiccall), - "xintrinsic and intrinsiccallwithtype call is not expected"); } return newCall; } @@ -1376,6 +1391,10 @@ BlockNode *CGLowerer::LowerCallAssignedStmt(StmtNode &stmt, bool uselvar) } case OP_intrinsiccallassigned: case OP_xintrinsiccallassigned: { + BlockNode *blockNode = LowerIntrinsiccallToIntrinsicop(stmt); + if (blockNode) { + return blockNode; + } IntrinsiccallNode &intrincall = static_cast(stmt); auto intrinsicID = intrincall.GetIntrinsic(); if (IntrinDesc::intrinTable[intrinsicID].IsAtomic()) { @@ -1397,6 +1416,10 @@ BlockNode *CGLowerer::LowerCallAssignedStmt(StmtNode &stmt, bool uselvar) break; } case OP_intrinsiccallwithtypeassigned: { + BlockNode *blockNode = LowerIntrinsiccallToIntrinsicop(stmt); + if (blockNode) { + return blockNode; + } auto &origCall = static_cast(stmt); newCall = GenIntrinsiccallNode(stmt, funcCalled, handledAtLowerLevel, origCall); p2nRets = &origCall.GetReturnVec(); @@ -1421,6 +1444,16 @@ BlockNode *CGLowerer::LowerCallAssignedStmt(StmtNode &stmt, bool uselvar) return GenBlockNode(*newCall, *p2nRets, stmt.GetOpCode(), funcCalled, handledAtLowerLevel, uselvar); } +BlockNode *CGLowerer::LowerIntrinsiccallToIntrinsicop(StmtNode &stmt) +{ + IntrinsiccallNode &intrinCall = static_cast(stmt); + auto intrinsicID = intrinCall.GetIntrinsic(); + if (IntrinDesc::intrinTable[intrinsicID].IsAtomic()) { + return LowerIntrinsiccallAassignedToAssignStmt(intrinCall); + } + return nullptr; +} + #if TARGAARCH64 static PrimType IsStructElementSame(MIRType *ty) { @@ -3690,9 +3723,12 @@ StmtNode *CGLowerer::LowerIntrinsiccall(IntrinsiccallNode &intrincall, BlockNode if (intrnID == INTRN_C_va_start) { return &intrincall; } + if (intrnID == maple::INTRN_C___builtin_division_exception) { + return &intrincall; + } IntrinDesc *intrinDesc = &IntrinDesc::intrinTable[intrnID]; if (intrinDesc->IsSpecial() || intrinDesc->IsAtomic()) { - /* For special intrinsics we leave them to CGFunc::SelectIntrinCall() */ + /* For special intrinsics we leave them to CGFunc::SelectIntrinsicCall() */ return &intrincall; } /* default lowers intrinsic call to real function call. */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cfi_generator.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cfi_generator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6fb3c1b3183c6d726220efe1edd15e6d7506dd92 --- /dev/null +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cfi_generator.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "aarch64_cfi_generator.h" +#include "aarch64_memlayout.h" +#include "aarch64_cgfunc.h" +namespace maplebe { +void AArch64GenCfi::GenerateRegisterSaveDirective(BB &bb, Insn &stackDefInsn) +{ + auto stackFrameSize = + static_cast(static_cast(cgFunc.GetMemlayout())->RealStackFrameSize()); + auto argsToStkPassSize = static_cast(cgFunc.GetMemlayout()->SizeOfArgsToStackPass()); + int32 cfiOffset = stackFrameSize; + auto *curInsn = InsertCFIDefCfaOffset(bb, stackDefInsn, cfiOffset); + cfiOffset = static_cast(GetOffsetFromCFA() - argsToStkPassSize); + auto &aarchCGFunc = static_cast(cgFunc); + + if (useFP) { + curInsn = bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiOffsetInsn(stackBaseReg, -cfiOffset, k64BitSize)); + } + int32 RLROffset = static_cast(cgFunc).GetStoreFP() ? kOffset8MemPos : 0; + curInsn = bb.InsertInsnAfter( + *curInsn, aarchCGFunc.CreateCfiOffsetInsn(RLR, static_cast(-cfiOffset + RLROffset), k64BitSize)); + + /* change CFA register and offset */ + if (useFP) { + bool isLmbc = cgFunc.GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc; + if ((argsToStkPassSize > 0) || isLmbc) { + curInsn = bb.InsertInsnAfter( + *curInsn, aarchCGFunc.CreateCfiDefCfaInsn(stackBaseReg, + static_cast(cgFunc.GetMemlayout())->RealStackFrameSize() - + static_cast(argsToStkPassSize) + cgFunc.GetFunction().GetFrameReseverdSlot(), + k64BitSize)); + } else { + curInsn = + bb.InsertInsnAfter(*curInsn, cgFunc.GetInsnBuilder() + ->BuildCfiInsn(cfi::OP_CFI_def_cfa_register) + .AddOpndChain(cgFunc.CreateCfiRegOperand(stackBaseReg, k64BitSize))); + } + } + + if (CGOptions::IsNoCalleeCFI()) { + return; + } + + /* callee save register cfi offset */ + auto ®sToSave = (aarchCGFunc.GetProEpilogSavedRegs().empty()) ? aarchCGFunc.GetCalleeSavedRegs() + : aarchCGFunc.GetProEpilogSavedRegs(); + if (regsToSave.empty()) { + return; + } + + auto it = regsToSave.begin(); + // skip the RFP + if (*it == RFP) { + ++it; + } + CHECK_FATAL(*it == RLR, "The second callee saved reg is expected to be RLR"); + ++it; + int32 offset = cgFunc.GetMemlayout()->GetCalleeSaveBaseLoc(); + for (; it != regsToSave.end(); ++it) { + AArch64reg reg = *it; + stackFrameSize -= static_cast(cgFunc.GetMemlayout()->SizeOfArgsToStackPass()); + cfiOffset = stackFrameSize - offset; + curInsn = bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiOffsetInsn(reg, -cfiOffset, k64BitSize)); + /* On AArch64, kIntregBytelen == 8 */ + offset += static_cast(kIntregBytelen); + } +} + +void AArch64GenCfi::GenerateRegisterRestoreDirective(BB &bb, Insn &stackRevertInsn) +{ + auto &aarchCGFunc = static_cast(cgFunc); + auto ®sToSave = (aarchCGFunc.GetProEpilogSavedRegs().empty()) ? aarchCGFunc.GetCalleeSavedRegs() + : aarchCGFunc.GetProEpilogSavedRegs(); + auto *curInsn = &stackRevertInsn; + + if (!regsToSave.empty()) { + auto it = regsToSave.begin(); + // skip the RFP + if (*it == RFP) { + ++it; + } + CHECK_FATAL(*it == RLR, "The second callee saved reg is expected to be RLR"); + ++it; + + if (!CGOptions::IsNoCalleeCFI()) { + for (; it != regsToSave.end(); ++it) { + AArch64reg reg = *it; + curInsn = bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiRestoreInsn(reg, k64BitSize)); + } + } + + if (useFP) { + curInsn = bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiRestoreInsn(stackBaseReg, k64BitSize)); + } + curInsn = bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiRestoreInsn(RLR, k64BitSize)); + } + // in aarch64 R31 is sp + bb.InsertInsnAfter(*curInsn, aarchCGFunc.CreateCfiDefCfaInsn(R31, 0, k64BitSize)); +} +} // namespace maplebe diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cg.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cg.cpp index 4e87cc7b0ee249ccf848e9475ce0c83ed588852e..904b556a6cd4b5b64cbfff524d8369630a683e70 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cg.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cg.cpp @@ -14,13 +14,15 @@ */ #include "aarch64_cg.h" +#include +#include "aarch64_mop_split.h" +#include "aarch64_mop_valid.h" #include "mir_builder.h" #include "becommon.h" #include "label_creation.h" #include "alignment.h" namespace maplebe { -#include "immvalid.def" #define DEFINE_MOP(...) {__VA_ARGS__}, const InsnDesc AArch64CG::kMd[kMopLast] = { #include "abstract_mmir.def" @@ -369,7 +371,8 @@ void AArch64CG::EnrollTargetPhases(MaplePhaseManager *pm) const Insn &AArch64CG::BuildPhiInsn(RegOperand &defOpnd, Operand &listParam) { DEBUG_ASSERT(defOpnd.IsRegister(), "build SSA on register operand"); - CHECK_FATAL(defOpnd.IsOfIntClass() || defOpnd.IsOfFloatOrSIMDClass(), " unknown operand type "); + /* There are cases that CCRegs need add phi insn. */ + CHECK_FATAL(defOpnd.IsOfIntClass() || defOpnd.IsOfFloatOrSIMDClass() || defOpnd.IsOfCC(), " unknown operand type "); bool is64bit = defOpnd.GetSize() == k64BitSize; MOperator mop = MOP_nop; if (defOpnd.GetSize() == k128BitSize) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp index 5c9fdccfc48f2e80d22121af56842ec132098e37..86142e207d73dcd8a364fb57c5cf8f8ac62823af 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_cgfunc.cpp @@ -62,7 +62,7 @@ MOperator ldIsAcq[kSignedDimension][kIntByteSizeDimension] = { /* unsigned == 0 */ {MOP_wldarb, MOP_wldarh, MOP_wldar, MOP_xldar}, /* signed == 1 */ - {MOP_undef, MOP_undef, MOP_wldar, MOP_xldar}}; + {MOP_wldarb, MOP_wldarh, MOP_wldar, MOP_xldar}}; MOperator stIsRel[kSignedDimension][kIntByteSizeDimension] = { /* unsigned == 0 */ @@ -130,7 +130,7 @@ MOperator PickLdStInsn(bool isLoad, uint32 bitSize, PrimType primType, AArch64is bitSize = k64BitSize; } uint32 size = static_cast(__builtin_ffs(static_cast(bitSize))) - k4BitSize; - DEBUG_ASSERT(size <= 3, "wrong bitSize"); // size must <= 3 + DEBUG_ASSERT(size <= 3, "wrong bitSize"); // size must <= 3 return table[signedUnsigned][size]; } else { MOperator *table = nullptr; @@ -381,9 +381,23 @@ void AArch64CGFunc::SelectCopyImm(Operand &dest, PrimType dType, ImmOperand &src void AArch64CGFunc::SelectCopyImm(Operand &dest, ImmOperand &src, PrimType dtype) { uint32 dsize = GetPrimTypeBitSize(dtype); + // If the type size of the parent node is smaller than the type size of the child node, + // the number of child node needs to be truncated. + if (dsize < src.GetSize()) { + uint64 value = static_cast(src.GetValue()); + uint64 mask = (1UL << dsize) - 1; + int64 newValue = static_cast(value & mask); + src.SetValue(newValue); + } DEBUG_ASSERT(IsPrimitiveInteger(dtype), "The type of destination operand must be Integer"); DEBUG_ASSERT(((dsize == k8BitSize) || (dsize == k16BitSize) || (dsize == k32BitSize) || (dsize == k64BitSize)), "The destination operand must be >= 8-bit"); + if (src.GetSize() == k32BitSize && dsize == k64BitSize && src.IsSingleInstructionMovable()) { + auto tempReg = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k32BitSize), k32BitSize, kRegTyInt); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_wmovri32, *tempReg, src)); + SelectCopy(dest, dtype, *tempReg, PTY_u32); + return; + } if (src.IsSingleInstructionMovable()) { MOperator mOp = (dsize == k32BitSize) ? MOP_wmovri32 : MOP_xmovri64; GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(mOp, dest, src)); @@ -642,7 +656,7 @@ void AArch64CGFunc::SplitMovImmOpndInstruction(int64 immVal, RegOperand &destReg } } - if (maxLoopTime == 2) { // compute lower 32 bits, and copy to higher 32 bits, so only 2 chunks need be processed + if (maxLoopTime == 2) { // compute lower 32 bits, and copy to higher 32 bits, so only 2 chunks need be processed /* copy lower 32 bits to higher 32 bits */ ImmOperand &immOpnd = CreateImmOperand(k32BitSize, k8BitSize, false); Insn &insn = GetInsnBuilder()->BuildInsn(MOP_xbfirri6i6, destReg, destReg, immOpnd, immOpnd); @@ -736,7 +750,7 @@ void AArch64CGFunc::SelectCopyRegOpnd(Operand &dest, PrimType dtype, Operand::Op } } -void AArch64CGFunc::SelectCopy(Operand &dest, PrimType dtype, Operand &src, PrimType stype) +void AArch64CGFunc::SelectCopy(Operand &dest, PrimType dtype, Operand &src, PrimType stype, BaseNode *baseNode) { DEBUG_ASSERT(dest.IsRegister() || dest.IsMemoryAccessOperand(), ""); uint32 dsize = GetPrimTypeBitSize(dtype); @@ -824,8 +838,9 @@ bool AArch64CGFunc::IsImmediateOffsetOutOfRange(const MemOperand &memOpnd, uint3 MemOperand::AArch64AddressingMode mode = memOpnd.GetAddrMode(); if ((mode == MemOperand::kAddrModeBOi) && memOpnd.IsIntactIndexed()) { - int32 offsetValue = static_cast(memOpnd.GetOffsetImmediate()->GetOffsetValue()); - if (memOpnd.GetOffsetImmediate()->GetVary() == kUnAdjustVary) { + OfstOperand *ofstOpnd = memOpnd.GetOffsetImmediate(); + int32 offsetValue = ofstOpnd ? static_cast(ofstOpnd->GetOffsetValue()) : 0; + if (ofstOpnd && ofstOpnd->GetVary() == kUnAdjustVary) { offsetValue += static_cast(static_cast(GetMemlayout())->RealStackFrameSize() + 0xff); } @@ -836,36 +851,46 @@ bool AArch64CGFunc::IsImmediateOffsetOutOfRange(const MemOperand &memOpnd, uint3 } } -bool AArch64CGFunc::IsOperandImmValid(MOperator mOp, Operand *o, uint32 opndIdx) +// This api is used to judge whether opnd is legal for mop. +// It is implemented by calling verify api of mop (InsnDesc -> Verify). +bool AArch64CGFunc::IsOperandImmValid(MOperator mOp, Operand *o, uint32 opndIdx) const { const InsnDesc *md = &AArch64CG::kMd[mOp]; auto *opndProp = md->opndMD[opndIdx]; - + MemPool *localMp = memPoolCtrler.NewMemPool("opnd verify mempool", true); + auto *localAlloc = new MapleAllocator(localMp); + MapleVector testOpnds(md->opndMD.size(), localAlloc->Adapter()); + testOpnds[opndIdx] = o; + bool flag = true; Operand::OperandType opndTy = opndProp->GetOperandType(); if (opndTy == Operand::kOpdMem) { auto *memOpnd = static_cast(o); - if (memOpnd->GetAddrMode() == MemOperand::kAddrModeBOrX) { + CHECK_FATAL(memOpnd != nullptr, "memOpnd should not be nullptr"); + if (memOpnd->GetAddrMode() == MemOperand::kAddrModeBOrX && + (!memOpnd->IsPostIndexed() && !memOpnd->IsPreIndexed())) { + delete localAlloc; + memPoolCtrler.DeleteMemPool(localMp); return true; } - if (md->IsLoadStorePair() || - (memOpnd->GetAddrMode() == MemOperand::kAddrModeBOi && memOpnd->IsIntactIndexed())) { - int64 offsetValue = memOpnd->GetOffsetImmediate()->GetOffsetValue(); - if (memOpnd->GetOffsetImmediate()->GetVary() == kUnAdjustVary) { - offsetValue += static_cast(GetMemlayout())->RealStackFrameSize() + 0xffL; - } - return md->IsValidImmOpnd(offsetValue); + OfstOperand *ofStOpnd = memOpnd->GetOffsetImmediate(); + int64 offsetValue = ofStOpnd ? ofStOpnd->GetOffsetValue() : 0LL; + if (md->IsLoadStorePair() || (memOpnd->GetAddrMode() == MemOperand::kAddrModeBOi)) { + flag = md->Verify(testOpnds); } else if (memOpnd->GetAddrMode() == MemOperand::kAddrModeLo12Li) { - int32 offsetValue = static_cast(memOpnd->GetOffsetImmediate()->GetOffsetValue()); - return offsetValue == 0; - } else { - CHECK_FATAL(!memOpnd->IsIntactIndexed(), "CHECK WHAT?"); - int32 offsetValue = static_cast(memOpnd->GetOffsetImmediate()->GetOffsetValue()); - return (offsetValue <= static_cast(k256BitSize) && offsetValue >= kNegative256BitSize); + if (offsetValue == 0) { + flag = md->Verify(testOpnds); + } else { + flag = false; + } + } else if (memOpnd->IsPostIndexed() || memOpnd->IsPreIndexed()) { + flag = (offsetValue <= static_cast(k256BitSizeInt) && offsetValue >= kNegative256BitSize); } } else if (opndTy == Operand::kOpdImmediate) { - return md->IsValidImmOpnd(static_cast(o)->GetValue()); + flag = md->Verify(testOpnds); } - return true; + delete localAlloc; + memPoolCtrler.DeleteMemPool(localMp); + return flag; } MemOperand &AArch64CGFunc::CreateReplacementMemOperand(uint32 bitLen, RegOperand &baseReg, int64 offset) @@ -909,27 +934,39 @@ RegOperand *AArch64CGFunc::GetBaseRegForSplit(uint32 baseRegNum) * Here we split the offset into (512 * n) and +/-(new Offset) when misaligned, to make sure that * the new offet is always under 256 bits. */ -MemOperand &AArch64CGFunc::ConstraintOffsetToSafeRegion(uint32 bitLen, const MemOperand &memOpnd) +MemOperand &AArch64CGFunc::ConstraintOffsetToSafeRegion(uint32 bitLen, const MemOperand &memOpnd, + const MIRSymbol *symbol) { auto it = hashMemOpndTable.find(memOpnd); if (it != hashMemOpndTable.end()) { hashMemOpndTable.erase(memOpnd); } + MemOperand::AArch64AddressingMode addrMode = memOpnd.GetAddrMode(); int32 offsetValue = static_cast(memOpnd.GetOffsetImmediate()->GetOffsetValue()); - int32 multiplier = (offsetValue / k512BitSize) + static_cast(offsetValue % k512BitSize > k256BitSize); - int32 addMount = multiplier * k512BitSizeInt; - int32 newOffset = offsetValue - addMount; RegOperand *baseReg = memOpnd.GetBaseRegister(); - ImmOperand &immAddMount = CreateImmOperand(addMount, k64BitSize, true); - if (memOpnd.GetOffsetImmediate()->GetVary() == kUnAdjustVary) { - immAddMount.SetVary(kUnAdjustVary); - } - RegOperand *resOpnd = GetBaseRegForSplit(kRinvalid); - SelectAdd(*resOpnd, *baseReg, immAddMount, PTY_i64); - MemOperand &newMemOpnd = CreateReplacementMemOperand(bitLen, *resOpnd, newOffset); - newMemOpnd.SetStackMem(memOpnd.IsStackMem()); - return newMemOpnd; + MemOperand *newMemOpnd = nullptr; + if (addrMode == MemOperand::kAddrModeBOi) { + int32 val256 = k256BitSizeInt; /* const val is unsigned */ + int32 val512 = k512BitSizeInt; + int32 multiplier = (offsetValue / val512) + static_cast(offsetValue % val512 > val256); + int32 addMount = multiplier * val512; + int32 newOffset = offsetValue - addMount; + ImmOperand &immAddMount = CreateImmOperand(addMount, k64BitSize, true); + if (memOpnd.GetOffsetImmediate()->GetVary() == kUnAdjustVary) { + immAddMount.SetVary(kUnAdjustVary); + } + SelectAdd(*resOpnd, *baseReg, immAddMount, PTY_i64); + newMemOpnd = &CreateReplacementMemOperand(bitLen, *resOpnd, newOffset); + } else if (addrMode == MemOperand::kAddrModeLo12Li) { + CHECK_FATAL(symbol != nullptr, "must have symbol"); + StImmOperand &stImmOpnd = CreateStImmOperand(*symbol, offsetValue, 0); + SelectAdd(*resOpnd, *baseReg, stImmOpnd, PTY_i64); + newMemOpnd = &CreateReplacementMemOperand(bitLen, *resOpnd, 0); + } + CHECK_FATAL(newMemOpnd != nullptr, "create memOpnd failed"); + newMemOpnd->SetStackMem(memOpnd.IsStackMem()); + return *newMemOpnd; } ImmOperand &AArch64CGFunc::SplitAndGetRemained(const MemOperand &memOpnd, uint32 bitLen, RegOperand *resOpnd, @@ -1025,17 +1062,18 @@ RegOperand *AArch64CGFunc::ExtractNewMemBase(const MemOperand &memOpnd) return nullptr; } RegOperand *baseOpnd = memOpnd.GetBaseRegister(); + OfstOperand *offsetOpnd = memOpnd.GetOffsetImmediate(); + int64 offset = (offsetOpnd == nullptr ? 0 : offsetOpnd->GetOffsetValue()); DEBUG_ASSERT(baseOpnd != nullptr, "nullptr check"); RegOperand &resultOpnd = CreateRegisterOperandOfType(baseOpnd->GetRegisterType(), baseOpnd->GetSize() / kBitsPerByte); bool is64Bits = (baseOpnd->GetSize() == k64BitSize); if (mode == MemOperand::kAddrModeLo12Li) { - StImmOperand &stImm = CreateStImmOperand(*sym, 0, 0); + StImmOperand &stImm = CreateStImmOperand(*sym, offset, 0); Insn &addInsn = GetInsnBuilder()->BuildInsn(MOP_xadrpl12, resultOpnd, *baseOpnd, stImm); addInsn.SetComment("new add insn"); GetCurBB()->AppendInsn(addInsn); } else if (mode == MemOperand::kAddrModeBOi) { - OfstOperand *offsetOpnd = memOpnd.GetOffsetImmediate(); if (offsetOpnd->GetOffsetValue() != 0) { MOperator mOp = is64Bits ? MOP_xaddrri12 : MOP_waddrri12; GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(mOp, resultOpnd, *baseOpnd, *offsetOpnd)); @@ -1119,7 +1157,8 @@ void AArch64CGFunc::SelectDassign(StIdx stIdx, FieldID fieldId, PrimType rhsPTyp } } - memOpnd = memOpnd->IsOffsetMisaligned(dataSize) ? &ConstraintOffsetToSafeRegion(dataSize, *memOpnd) : memOpnd; + memOpnd = + memOpnd->IsOffsetMisaligned(dataSize) ? &ConstraintOffsetToSafeRegion(dataSize, *memOpnd, symbol) : memOpnd; if (symbol->GetAsmAttr() != UStrIdx(0) && symbol->GetStorageClass() != kScPstatic && symbol->GetStorageClass() != kScFstatic) { std::string regDesp = GlobalTables::GetUStrTable().GetStringFromStrIdx(symbol->GetAsmAttr()); @@ -1152,7 +1191,7 @@ void AArch64CGFunc::SelectDassignoff(DassignoffNode &stmt, Operand &opnd0) memOpnd = &SplitOffsetWithAddInstruction(*memOpnd, size); } Operand &stOpnd = LoadIntoRegister(opnd0, true, size, false); - memOpnd = memOpnd->IsOffsetMisaligned(size) ? &ConstraintOffsetToSafeRegion(size, *memOpnd) : memOpnd; + memOpnd = memOpnd->IsOffsetMisaligned(size) ? &ConstraintOffsetToSafeRegion(size, *memOpnd, symbol) : memOpnd; Insn &insn = GetInsnBuilder()->BuildInsn(mOp, stOpnd, *memOpnd); GetCurBB()->AppendInsn(insn); } @@ -1181,6 +1220,8 @@ void AArch64CGFunc::SelectAbort() movXzr.SetDoNotRemove(true); GetCurBB()->AppendInsn(movXzr); GetCurBB()->AppendInsn(loadRef); + SetCurBBKind(BB::kBBReturn); + GetExitBBsVec().emplace_back(GetCurBB()); } static std::string GetRegPrefixFromPrimType(PrimType pType, uint32 size, const std::string &constraint) @@ -1265,6 +1306,68 @@ void AArch64CGFunc::SelectAsm(AsmNode &node) } break; } + case OP_addrofoff: { + auto &addrofoffNode = static_cast(*node.Opnd(i)); + Operand *inOpnd = SelectAddrofoff(addrofoffNode, node); + listInputOpnd->PushOpnd(static_cast(*inOpnd)); + PrimType pType = addrofoffNode.GetPrimType(); + listInRegPrefix->stringList.push_back(static_cast( + &CreateStringOperand(GetRegPrefixFromPrimType(pType, inOpnd->GetSize(), str)))); + if (isOutputTempNode) { + rPlusOpnd.emplace_back(std::make_pair(inOpnd, pType)); + } + break; + } + case OP_ireadoff: { + auto *ireadoff = static_cast(node.Opnd(i)); + Operand *inOpnd = SelectIreadoff(node, *ireadoff); + listInputOpnd->PushOpnd(static_cast(*inOpnd)); + PrimType pType = ireadoff->GetPrimType(); + listInRegPrefix->stringList.push_back(static_cast( + &CreateStringOperand(GetRegPrefixFromPrimType(pType, inOpnd->GetSize(), str)))); + if (isOutputTempNode) { + rPlusOpnd.emplace_back(std::make_pair(inOpnd, pType)); + } + break; + } + case OP_ireadfpoff: { + auto *ireadfpoff = static_cast(node.Opnd(i)); + Operand *inOpnd = SelectIreadfpoff(node, *ireadfpoff); + listInputOpnd->PushOpnd(static_cast(*inOpnd)); + PrimType pType = ireadfpoff->GetPrimType(); + listInRegPrefix->stringList.push_back(static_cast( + &CreateStringOperand(GetRegPrefixFromPrimType(pType, inOpnd->GetSize(), str)))); + if (isOutputTempNode) { + rPlusOpnd.emplace_back(std::make_pair(inOpnd, pType)); + } + break; + } + case OP_iread: { + auto *iread = static_cast(node.Opnd(i)); + Operand *inOpnd = SelectIread(node, *iread); + listInputOpnd->PushOpnd(static_cast(*inOpnd)); + PrimType pType = iread->GetPrimType(); + listInRegPrefix->stringList.push_back(static_cast( + &CreateStringOperand(GetRegPrefixFromPrimType(pType, inOpnd->GetSize(), str)))); + if (isOutputTempNode) { + rPlusOpnd.emplace_back(std::make_pair(inOpnd, pType)); + } + break; + } + case OP_add: { + auto *addNode = static_cast(node.Opnd(i)); + Operand *inOpnd = SelectAdd(*addNode, *HandleExpr(*addNode, *addNode->Opnd(0)), + *HandleExpr(*addNode, *addNode->Opnd(1)), node); + listInputOpnd->PushOpnd(static_cast(*inOpnd)); + PrimType pType = addNode->GetPrimType(); + listInRegPrefix->stringList.push_back(static_cast( + &CreateStringOperand(GetRegPrefixFromPrimType(pType, inOpnd->GetSize(), str)))); + if (isOutputTempNode) { + rPlusOpnd.emplace_back(std::make_pair(inOpnd, pType)); + } + break; + } + case OP_constval: { CHECK_FATAL(!isOutputTempNode, "Unexpect"); auto &constNode = static_cast(*node.Opnd(i)); @@ -1404,7 +1507,7 @@ void AArch64CGFunc::SelectAsm(AsmNode &node) for (size_t i = 0; i < node.clobberList.size(); ++i) { std::string str = GlobalTables::GetUStrTable().GetStringFromStrIdx(node.clobberList[i]); auto regno = static_cast(str[1] - '0'); - if (str[2] >= '0' && str[2] <= '9') { // if third char (index 2) is num, add to regno + if (str[2] >= '0' && str[2] <= '9') { // if third char (index 2) is num, add to regno regno = regno * kDecimalMax + static_cast((str[2] - '0')); } RegOperand *reg; @@ -1454,11 +1557,11 @@ void AArch64CGFunc::SelectRegassign(RegassignNode &stmt, Operand &opnd0) PrimType lhsSize = stmt.GetPrimType(); PrimType rhsSize = stmt.Opnd(0)->GetPrimType(); if (lhsSize != rhsSize && stmt.Opnd(0)->GetOpCode() == OP_ireadoff) { - Insn *prev = GetCurBB()->GetLastInsn(); - if (prev->GetMachineOpcode() == MOP_wldrsb || prev->GetMachineOpcode() == MOP_wldrsh) { + Insn *prev = GetCurBB()->GetLastMachineInsn(); + if (prev && (prev->GetMachineOpcode() == MOP_wldrsb || prev->GetMachineOpcode() == MOP_wldrsh)) { opnd0.SetSize(GetPrimTypeBitSize(stmt.GetPrimType())); prev->SetMOP(AArch64CG::kMd[prev->GetMachineOpcode() == MOP_wldrsb ? MOP_xldrsb : MOP_xldrsh]); - } else if (prev->GetMachineOpcode() == MOP_wldr && stmt.GetPrimType() == PTY_i64) { + } else if (prev && (prev->GetMachineOpcode() == MOP_wldr && stmt.GetPrimType() == PTY_i64)) { opnd0.SetSize(GetPrimTypeBitSize(stmt.GetPrimType())); prev->SetMOP(AArch64CG::kMd[MOP_xldrsw]); } @@ -1488,13 +1591,15 @@ void AArch64CGFunc::SelectRegassign(RegassignNode &stmt, Operand &opnd0) /* The subtree should already taken care of the agg type that is in excess of 8 bytes */ rhsType = PTY_i64; } - PrimType dtype = rhsType; - if (GetPrimTypeBitSize(dtype) < k32BitSize) { - DEBUG_ASSERT(IsPrimitiveInteger(dtype), ""); - dtype = IsSignedInteger(dtype) ? PTY_i32 : PTY_u32; - } DEBUG_ASSERT(regOpnd != nullptr, "null ptr check!"); - SelectCopy(*regOpnd, dtype, opnd0, rhsType); + Operand *srcOpnd = &opnd0; + if (GetPrimTypeSize(stmt.GetPrimType()) > GetPrimTypeSize(rhsType) && IsPrimitiveInteger(rhsType)) { + CHECK_FATAL(IsPrimitiveInteger(stmt.GetPrimType()), "NIY"); + srcOpnd = &CreateRegisterOperandOfType(stmt.GetPrimType()); + SelectCvtInt2Int(nullptr, srcOpnd, &opnd0, rhsType, stmt.GetPrimType()); + } + SelectCopy(*regOpnd, stmt.GetPrimType(), *srcOpnd, rhsType, stmt.GetRHS()); + if (GetCG()->GenerateVerboseCG()) { if (GetCurBB()->GetLastInsn()) { GetCurBB()->GetLastInsn()->AppendComment(" regassign %" + std::to_string(pregIdx) + "; "); @@ -1912,7 +2017,7 @@ void AArch64CGFunc::SelectAggDassign(DassignNode &stmt) lhsSizeCovered += newAlignUsed; } } else { - DEBUG_ASSERT(stmt.GetRHS()->op == OP_regread, "SelectAggDassign: NYI"); + CHECK_FATAL(stmt.GetRHS()->op == OP_regread, "SelectAggDassign: NYI"); bool isRet = false; if (lhsType->GetKind() == kTypeStruct || lhsType->GetKind() == kTypeUnion) { RegreadNode *rhsregread = static_cast(stmt.GetRHS()); @@ -2020,7 +2125,7 @@ void AArch64CGFunc::SelectIassign(IassignNode &stmt) DEBUG_ASSERT(stmt.Opnd(0) != nullptr, "null ptr check"); MemOperand &memOpnd = CreateMemOpnd(destType, stmt, *stmt.Opnd(0), offset); auto dataSize = GetPrimTypeBitSize(destType); - memOpnd = memOpnd.IsOffsetMisaligned(dataSize) ? ConstraintOffsetToSafeRegion(dataSize, memOpnd) : memOpnd; + memOpnd = memOpnd.IsOffsetMisaligned(dataSize) ? ConstraintOffsetToSafeRegion(dataSize, memOpnd, nullptr) : memOpnd; if (isVolStore && memOpnd.GetAddrMode() == MemOperand::kAddrModeBOi) { memOrd = AArch64isa::kMoRelease; isVolStore = false; @@ -2031,7 +2136,9 @@ void AArch64CGFunc::SelectIassign(IassignNode &stmt) } else { AArch64CGFunc::SelectStoreRelease(memOpnd, destType, srcOpnd, destType, memOrd, false); } - GetCurBB()->GetLastInsn()->MarkAsAccessRefField(isRefField); + if (GetCurBB() && GetCurBB()->GetLastMachineInsn()) { + GetCurBB()->GetLastMachineInsn()->MarkAsAccessRefField(isRefField); + } } void AArch64CGFunc::SelectIassignoff(IassignoffNode &stmt) @@ -2041,7 +2148,7 @@ void AArch64CGFunc::SelectIassignoff(IassignoffNode &stmt) MemOperand &memOpnd = CreateMemOpnd(destType, stmt, *stmt.GetBOpnd(0), offset); auto dataSize = GetPrimTypeBitSize(destType); - memOpnd = memOpnd.IsOffsetMisaligned(dataSize) ? ConstraintOffsetToSafeRegion(dataSize, memOpnd) : memOpnd; + memOpnd = memOpnd.IsOffsetMisaligned(dataSize) ? ConstraintOffsetToSafeRegion(dataSize, memOpnd, nullptr) : memOpnd; Operand *valOpnd = HandleExpr(stmt, *stmt.GetBOpnd(1)); Operand &srcOpnd = LoadIntoRegister(*valOpnd, true, GetPrimTypeBitSize(destType)); SelectCopy(memOpnd, destType, srcOpnd, destType); @@ -2162,72 +2269,81 @@ MIRType *AArch64CGFunc::LmbcGetAggTyFromCallSite(StmtNode *stmt, std::vector(static_cast(src)->GetRegisterNumber()); MIRFunction *func = &GetFunction(); - if (func->IsReturnStruct()) { - /* This blkassignoff is for struct return? */ - uint32 loadSize; - uint32 numRegs = 0; - if (bNode.GetNext()->GetOpCode() == OP_return) { - MIRStructType *ty = static_cast( - GlobalTables::GetTypeTable().GetTypeFromTyIdx(func->GetFuncRetStructTyIdx())); - uint32 fpregs = FloatParamRegRequired(ty, size); - if (fpregs > 0) { - /* pure floating point in agg */ - numRegs = fpregs; - pTy = (size == k4ByteSize) ? PTY_f32 : PTY_f64; - loadSize = GetPrimTypeSize(pTy) * kBitsPerByte; - for (uint32 i = 0; i < fpregs; i++) { - int32 s = (i == 0) ? 0 : static_cast(i * size); - MemOperand &mem = CreateMemOpnd(regno, s, size * kBitsPerByte); - AArch64reg reg = static_cast(V0 + i); - RegOperand *res = &GetOrCreatePhysicalRegisterOperand(reg, loadSize, kRegTyFloat); - SelectCopy(*res, pTy, mem, pTy); - } - } else { - /* int/float mixed */ - numRegs = kRegNum2; - pTy = PTY_i64; - size = k4ByteSize; - switch (bNode.blockSize) { - case k1ByteSize: - pTy = PTY_i8; - break; - case k2ByteSize: - pTy = PTY_i16; - break; - case k4ByteSize: - pTy = PTY_i32; - break; - default: - size = k8ByteSize; /* pTy remains i64 */ - break; - } - loadSize = GetPrimTypeSize(pTy) * kBitsPerByte; - MemOperand &mem = CreateMemOpnd(regno, 0, size * kBitsPerByte); - RegOperand *res = &GetOrCreatePhysicalRegisterOperand(R0, loadSize, kRegTyInt); + if (!func->IsReturnStruct()) { + return false; + } + /* This blkassignoff is for struct return? */ + uint32 loadSize; + uint32 numRegs = 0; + if (static_cast(bNode).GetNext()->GetOpCode() == OP_return) { + MIRStructType *ty = static_cast(func->GetReturnType()); + uint32 tySize = GetBecommon().GetTypeSize(ty->GetTypeIndex()); + uint32 fpregs = FloatParamRegRequired(ty, size); + if (fpregs > 0) { + /* pure floating point in agg */ + numRegs = fpregs; + pTy = (size == k4ByteSize) ? PTY_f32 : PTY_f64; + loadSize = GetPrimTypeSize(pTy) * kBitsPerByte; + for (uint32 i = 0; i < fpregs; i++) { + int32 s = (i == 0) ? 0 : static_cast(i * size); + int64 newOffset = static_cast(s) + static_cast(offset); + MemOperand &mem = CreateMemOpnd(regno, newOffset, size * kBitsPerByte); + AArch64reg reg = static_cast(V0 + i); + RegOperand *res = &GetOrCreatePhysicalRegisterOperand(reg, loadSize, kRegTyFloat); SelectCopy(*res, pTy, mem, pTy); - if (bNode.blockSize > static_cast(k8ByteSize)) { - MemOperand &newMem = CreateMemOpnd(regno, k8ByteSize, size * kBitsPerByte); - res = &GetOrCreatePhysicalRegisterOperand(R1, loadSize, kRegTyInt); - SelectCopy(*res, pTy, newMem, pTy); - } } - bool intReg = fpregs == 0; - for (uint32 i = 0; i < numRegs; i++) { - AArch64reg preg = static_cast((intReg ? R0 : V0) + i); - MOperator mop = intReg ? MOP_pseudo_ret_int : MOP_pseudo_ret_float; - RegOperand &dest = GetOrCreatePhysicalRegisterOperand(preg, loadSize, intReg ? kRegTyInt : kRegTyFloat); - Insn &pseudo = GetInsnBuilder()->BuildInsn(mop, dest); - GetCurBB()->AppendInsn(pseudo); + } else { + constexpr uint8 numRegMax = 2; + /* int/float mixed */ + numRegs = numRegMax; + pTy = PTY_i64; + constexpr uint32 oneByte = 1; + constexpr uint32 twoByte = 2; + constexpr uint32 fourByte = 4; + size = k4ByteSize; + switch (tySize) { + case oneByte: + pTy = PTY_i8; + break; + case twoByte: + pTy = PTY_i16; + break; + case fourByte: + pTy = PTY_i32; + break; + default: + size = k8ByteSize; /* pTy remains i64 */ + break; + } + loadSize = GetPrimTypeSize(pTy) * kBitsPerByte; + if (!skip1) { + MemOperand &mem = CreateMemOpnd(regno, offset, size * kBitsPerByte); + RegOperand &res1 = GetOrCreatePhysicalRegisterOperand(R0, loadSize, kRegTyInt); + SelectCopy(res1, pTy, mem, pTy); + } + if (tySize > static_cast(k8ByteSize)) { + int32 newOffset = offset + static_cast(k8ByteSize); + MemOperand &newMem = CreateMemOpnd(regno, newOffset, size * kBitsPerByte); + RegOperand &res2 = GetOrCreatePhysicalRegisterOperand(R1, loadSize, kRegTyInt); + SelectCopy(res2, pTy, newMem, pTy); } - return true; } + bool intReg = fpregs == 0; + for (uint32 i = 0; i < numRegs; i++) { + AArch64reg preg = static_cast((intReg ? R0 : V0) + i); + MOperator mop = intReg ? MOP_pseudo_ret_int : MOP_pseudo_ret_float; + RegOperand &dest = GetOrCreatePhysicalRegisterOperand(preg, loadSize, intReg ? kRegTyInt : kRegTyFloat); + Insn &pseudo = GetInsnBuilder()->BuildInsn(mop, dest); + GetCurBB()->AppendInsn(pseudo); + } + return true; } return false; } @@ -2377,17 +2493,19 @@ void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd) DEBUG_ASSERT(stmt.Opnd(0) != nullptr, "null ptr check"); Operand &lhsAddrOpnd = LoadIntoRegister(AddrOpnd, stmt.Opnd(0)->GetPrimType()); uint32 lhsOffset = 0; - MIRType *stmtType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(stmt.GetTyIdx()); - MIRPtrType *lhsPointerType = static_cast(stmtType); bool loadToRegs4StructReturn = false; if (mirModule.CurFunction()->StructReturnedInRegs()) { - MIRSymbol *retSt = mirModule.CurFunction()->GetFormal(0); + MIRSymbol *retSt = + mirModule.CurFunction()->GetFormalCount() == 0 ? nullptr : mirModule.CurFunction()->GetFormal(0); if (stmt.Opnd(0)->GetOpCode() == OP_dread) { DreadNode *dread = static_cast(stmt.Opnd(0)); MIRSymbol *addrSym = mirModule.CurFunction()->GetLocalOrGlobalSymbol(dread->GetStIdx()); loadToRegs4StructReturn = (retSt == addrSym); } } + + MIRType *stmtType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(stmt.GetTyIdx()); + MIRPtrType *lhsPointerType = static_cast(stmtType); MIRType *lhsType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(lhsPointerType->GetPointedTyIdx()); if (stmt.GetFieldID() != 0) { MIRStructType *structType = static_cast(lhsType); @@ -2635,42 +2753,6 @@ void AArch64CGFunc::SelectAggIassign(IassignNode &stmt, Operand &AddrOpnd) rhsOffset = static_cast(GetBecommon().GetFieldOffset(*rhsStructType, rhsIread->GetFieldID()).first); isRefField = GetBecommon().IsRefField(*rhsStructType, rhsIread->GetFieldID()); } - if (loadToRegs4StructReturn) { - /* generate move to regs. */ - CHECK_FATAL(lhsSize <= k16ByteSize, "SelectAggIassign: illegal struct size"); - RegOperand *result[kTwoRegister]; /* maximum 16 bytes, 2 registers */ - uint32 loadSize; - if (CGOptions::IsBigEndian()) { - loadSize = k8ByteSize; - } else { - loadSize = (lhsSize <= k4ByteSize) ? k4ByteSize : k8ByteSize; - } - uint32 numRegs = (lhsSize <= k8ByteSize) ? kOneRegister : kTwoRegister; - for (uint32 i = 0; i < numRegs; i++) { - OfstOperand *rhsOffOpnd = &GetOrCreateOfstOpnd(rhsOffset + i * loadSize, loadSize * kBitsPerByte); - Operand &rhsmemopnd = GetOrCreateMemOpnd(MemOperand::kAddrModeBOi, loadSize * kBitsPerByte, rhsAddrOpnd, - nullptr, rhsOffOpnd, nullptr); - result[i] = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, loadSize)); - MOperator mop1 = PickLdInsn(loadSize * kBitsPerByte, PTY_u32); - Insn &ld = GetInsnBuilder()->BuildInsn(mop1, *(result[i]), rhsmemopnd); - ld.MarkAsAccessRefField(isRefField); - GetCurBB()->AppendInsn(ld); - } - for (uint32 i = 0; i < numRegs; i++) { - AArch64reg preg = (i == 0 ? R0 : R1); - RegOperand &dest = GetOrCreatePhysicalRegisterOperand(preg, loadSize * kBitsPerByte, kRegTyInt); - Insn &mov = GetInsnBuilder()->BuildInsn(MOP_xmovrr, dest, *(result[i])); - GetCurBB()->AppendInsn(mov); - } - /* Create artificial dependency to extend the live range */ - for (uint32 i = 0; i < numRegs; i++) { - AArch64reg preg = (i == 0 ? R0 : R1); - RegOperand &dest = GetOrCreatePhysicalRegisterOperand(preg, loadSize * kBitsPerByte, kRegTyInt); - Insn &pseudo = GetInsnBuilder()->BuildInsn(MOP_pseudo_ret_int, dest); - GetCurBB()->AppendInsn(pseudo); - } - return; - } rhsAlign = GetBecommon().GetTypeAlign(rhsType->GetTypeIndex()); alignUsed = std::min(lhsAlign, rhsAlign); DEBUG_ASSERT(alignUsed != 0, "expect non-zero"); @@ -2897,6 +2979,9 @@ void AArch64CGFunc::SelectReturnSendOfStructInRegs(BaseNode *x) Insn &ld = GetInsnBuilder()->BuildInsn(mop1, *(result[i]), rhsmemopnd); ld.MarkAsAccessRefField(isRefField); GetCurBB()->AppendInsn(ld); + if (!VERIFY_INSN(&ld)) { + SPLIT_INSN(&ld, this); + } } RegOperand *dest; for (uint32 i = 0; i < numRegs; i++) { @@ -2966,10 +3051,13 @@ Operand *AArch64CGFunc::SelectDread(const BaseNode &parent, DreadNode &expr) uint32 dataSize = GetPrimTypeBitSize(symType); uint32 aggSize = 0; + PrimType resultType = expr.GetPrimType(); if (symType == PTY_agg) { if (expr.GetPrimType() == PTY_agg) { aggSize = static_cast(GetBecommon().GetTypeSize(symbol->GetType()->GetTypeIndex().GetIdx())); dataSize = ((expr.GetFieldID() == 0) ? GetPointerSize() : aggSize) << k8BitShift; + resultType = PTY_u64; + symType = resultType; } else { dataSize = GetPrimTypeBitSize(expr.GetPrimType()); } @@ -3010,7 +3098,6 @@ Operand *AArch64CGFunc::SelectDread(const BaseNode &parent, DreadNode &expr) memOpnd = &SplitOffsetWithAddInstruction(*memOpnd, dataSize); } - PrimType resultType = expr.GetPrimType(); RegOperand &resOpnd = GetOrCreateResOperand(parent, symType); /* a local register variable defined with a specified register */ if (symbol->GetAsmAttr() != UStrIdx(0) && symbol->GetStorageClass() != kScPstatic && @@ -3019,7 +3106,8 @@ Operand *AArch64CGFunc::SelectDread(const BaseNode &parent, DreadNode &expr) RegOperand &specifiedOpnd = GetOrCreatePhysicalRegisterOperand(regDesp); return &specifiedOpnd; } - memOpnd = memOpnd->IsOffsetMisaligned(dataSize) ? &ConstraintOffsetToSafeRegion(dataSize, *memOpnd) : memOpnd; + memOpnd = + memOpnd->IsOffsetMisaligned(dataSize) ? &ConstraintOffsetToSafeRegion(dataSize, *memOpnd, symbol) : memOpnd; SelectCopy(resOpnd, resultType, *memOpnd, symType); return &resOpnd; } @@ -3313,9 +3401,21 @@ Operand *AArch64CGFunc::SelectIreadoff(const BaseNode &parent, IreadoffNode &ire auto *baseAddr = ireadoff.Opnd(0); auto *result = &CreateRegisterOperandOfType(primType); auto *addrOpnd = HandleExpr(ireadoff, *baseAddr); - auto &memOpnd = CreateMemOpnd(LoadIntoRegister(*addrOpnd, PTY_a64), offset, bitSize); - auto mop = PickLdInsn(bitSize, primType); - GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(mop, *result, memOpnd)); + ASSERT_NOT_NULL(addrOpnd); + if (primType == PTY_agg && parent.GetOpCode() == OP_regassign) { + auto &memOpnd = CreateMemOpnd(LoadIntoRegister(*addrOpnd, PTY_a64), offset, bitSize); + auto mop = PickLdInsn(64, PTY_a64); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(mop, *result, memOpnd)); + auto ®AssignNode = static_cast(parent); + PregIdx pIdx = regAssignNode.GetRegIdx(); + CHECK_FATAL(IsSpecialPseudoRegister(pIdx), "SelectIreadfpoff of agg"); + (void)LmbcSmallAggForRet(parent, addrOpnd, offset, true); + // result not used + } else { + auto &memOpnd = CreateMemOpnd(LoadIntoRegister(*addrOpnd, PTY_a64), offset, bitSize); + auto mop = PickLdInsn(bitSize, primType); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(mop, *result, memOpnd)); + } return result; } @@ -3457,7 +3557,8 @@ Operand *AArch64CGFunc::SelectIread(const BaseNode &parent, IreadNode &expr, int regSize = k4ByteSize; /* 32-bit */ } Operand *result = nullptr; - if (parent.GetOpCode() == OP_eval) { + constexpr int regSizeMax = 8; + if (parent.GetOpCode() == OP_eval && regSize <= regSizeMax) { /* regSize << 3, that is regSize * 8, change bytes to bits */ result = &GetZeroOpnd(regSize << 3); } else { @@ -3498,13 +3599,16 @@ Operand *AArch64CGFunc::SelectIread(const BaseNode &parent, IreadNode &expr, int break; default: destType = PTY_u64; // when eval agg . a way to round up + DEBUG_ASSERT(bitSize == 0, " round up empty agg "); + bitSize = k64BitSize; break; } } } - MemOperand *memOpnd = - CreateMemOpndOrNull(destType, expr, *expr.Opnd(0), static_cast(offset) + extraOffset, memOrd); + PrimType memType = (finalBitFieldDestType == kPtyInvalid ? destType : finalBitFieldDestType); + MemOperand *memOpnd = CreateMemOpndOrNull(memType, expr, *expr.Opnd(0), + static_cast(static_cast(offset) + extraOffset), memOrd); if (aggParamReg != nullptr) { isAggParamInReg = false; return aggParamReg; @@ -3515,7 +3619,8 @@ Operand *AArch64CGFunc::SelectIread(const BaseNode &parent, IreadNode &expr, int isVolLoad = false; } - memOpnd = memOpnd->IsOffsetMisaligned(bitSize) ? &ConstraintOffsetToSafeRegion(bitSize, *memOpnd) : memOpnd; + memOpnd = + memOpnd->IsOffsetMisaligned(bitSize) ? &ConstraintOffsetToSafeRegion(bitSize, *memOpnd, nullptr) : memOpnd; if (memOrd == AArch64isa::kMoNone) { MOperator mOp = 0; if (finalBitFieldDestType == kPtyInvalid) { @@ -3547,6 +3652,7 @@ Operand *AArch64CGFunc::SelectIread(const BaseNode &parent, IreadNode &expr, int case PTY_i32: mOp = MOP_xsxtw64; break; + case PTY_u1: case PTY_u8: mOp = MOP_xuxtb32; break; @@ -3559,6 +3665,12 @@ Operand *AArch64CGFunc::SelectIread(const BaseNode &parent, IreadNode &expr, int default: break; } + if (destType == PTY_u1) { + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_wandrri12, insn.GetOperand(0), + insn.GetOperand(0), + CreateImmOperand(1, kMaxImmVal5Bits, false))); + } + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(mOp, insn.GetOperand(0), insn.GetOperand(0))); } } @@ -3568,10 +3680,21 @@ Operand *AArch64CGFunc::SelectIread(const BaseNode &parent, IreadNode &expr, int } AArch64CGFunc::SelectLoadAcquire(*result, destType, *memOpnd, destType, memOrd, false); } - GetCurBB()->GetLastInsn()->MarkAsAccessRefField(isRefField); + if (GetCurBB() && GetCurBB()->GetLastMachineInsn()) { + GetCurBB()->GetLastMachineInsn()->MarkAsAccessRefField(isRefField); + } return result; } +Operand *AArch64CGFunc::SelectIntConst(const MIRIntConst &intConst, const BaseNode &parent) +{ + auto primType = intConst.GetType().GetPrimType(); + if (kOpcodeInfo.IsCompare(parent.GetOpCode())) { + primType = static_cast(parent).GetOpndType(); + } + return &CreateImmOperand(intConst.GetExtValue(), GetPrimTypeBitSize(primType), false); +} + Operand *AArch64CGFunc::SelectIntConst(const MIRIntConst &intConst) { return &CreateImmOperand(intConst.GetExtValue(), GetPrimTypeSize(intConst.GetType().GetPrimType()) * kBitsPerByte, @@ -4079,6 +4202,13 @@ void AArch64CGFunc::SelectAdd(Operand &resOpnd, Operand &opnd0, Operand &opnd1, IsPrimitiveFloat(primType) ? (is64Bits ? MOP_dadd : MOP_sadd) : (is64Bits ? MOP_xaddrrr : MOP_waddrrr); GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(mOp, resOpnd, opnd0, opnd1)); return; + } else if (opnd1Type == Operand::kOpdStImmediate) { + CHECK_FATAL(is64Bits, "baseReg of mem in aarch64 must be 64bit size"); + /* add reg, reg, #:lo12:sym+offset */ + StImmOperand &stImmOpnd = static_cast(opnd1); + Insn &newInsn = GetInsnBuilder()->BuildInsn(MOP_xadrpl12, resOpnd, opnd0, stImmOpnd); + GetCurBB()->AppendInsn(newInsn); + return; } else if (!((opnd1Type == Operand::kOpdImmediate) || (opnd1Type == Operand::kOpdOffset))) { /* add reg, otheregType */ SelectAdd(resOpnd, opnd0, SelectCopy(opnd1, primType, primType), primType); @@ -4382,7 +4512,7 @@ void AArch64CGFunc::SelectMpy(Operand &resOpnd, Operand &opnd0, Operand &opnd1, } return; - } else if (immValue > 2) { // immValue should larger than 2 + } else if (immValue > 2) { // immValue should larger than 2 uint32 zeroNum = __builtin_ffsll(immValue) - 1; int64 headVal = static_cast(immValue) >> zeroNum; /* @@ -4390,7 +4520,8 @@ void AArch64CGFunc::SelectMpy(Operand &resOpnd, Operand &opnd0, Operand &opnd1, * otherOp * immVal = (otherOp * (immVal >> zeroNum) * (1 << zeroNum) * = (otherOp * ((immVal >> zeroNum) - 1) + otherOp) * (1 << zeroNum) */ - if (((static_cast(headVal) - 1) & (static_cast(headVal) - 2)) == 0) { // 2 see comment above + if (((static_cast(headVal) - 1) & (static_cast(headVal) - 2)) == + 0) { // 2 see comment above if (otherOp->GetKind() != Operand::kOpdRegister) { otherOp = &SelectCopy(*otherOp, primType, primType); } @@ -4562,7 +4693,7 @@ void AArch64CGFunc::SelectRem(Operand &resOpnd, Operand &lhsOpnd, Operand &rhsOp */ if ((Globals::GetInstance()->GetOptimLevel() >= CGOptions::kLevel2)) { ImmOperand *imm = nullptr; - Insn *movImmInsn = GetCurBB()->GetLastInsn(); + Insn *movImmInsn = GetCurBB()->GetLastMachineInsn(); if (movImmInsn && ((movImmInsn->GetMachineOpcode() == MOP_wmovri32) || (movImmInsn->GetMachineOpcode() == MOP_xmovri64)) && movImmInsn->GetOperand(0).Equals(opnd1)) { @@ -4674,7 +4805,7 @@ Operand *AArch64CGFunc::SelectLand(BinaryNode &node, Operand &lhsOpnd, Operand & Operand &opnd0 = LoadIntoRegister(lhsOpnd, primType); SelectAArch64Cmp(opnd0, CreateImmOperand(0, primType, false), true, GetPrimTypeBitSize(primType)); Operand &opnd1 = LoadIntoRegister(rhsOpnd, primType); - constexpr int64 immValue4 = 4; //integer as comment above + constexpr int64 immValue4 = 4; // integer as comment above SelectAArch64CCmp(opnd1, CreateImmOperand(0, primType, false), CreateImmOperand(immValue4, PTY_u8, false), GetCondOperand(CC_NE), is64Bits); SelectAArch64CSet(resOpnd, GetCondOperand(CC_NE), is64Bits); @@ -5060,7 +5191,7 @@ void AArch64CGFunc::SelectRelationOperator(RelationOperator operatorCode, Operan if (bitNum <= k16ValidBit) { int64 newImm = (static_cast(immVal) >> static_cast(tail0BitNum)) & 0xFFFF; - ImmOperand &immOpnd1 = CreateImmOperand(newImm, k16BitSize, false); + ImmOperand &immOpnd1 = CreateImmOperand(newImm, k32BitSize, false); SelectCopyImm(regOpnd, immOpnd1, primType); MOperator mOp = SelectRelationMop(operatorCode, kRegImm, is64Bits, false, true); int32 bitLen = is64Bits ? kBitLenOfShift64Bits : kBitLenOfShift32Bits; @@ -5294,7 +5425,7 @@ Operand *AArch64CGFunc::SelectAbsSub(Insn &lastInsn, const UnaryNode &node, Oper uint32 mopCsneg = is64Bits ? MOP_xcnegrrrc : MOP_wcnegrrrc; /* ABS requires the operand be interpreted as a signed integer */ CondOperand &condOpnd = GetCondOperand(CC_MI); - MOperator newMop = lastInsn.GetMachineOpcode() + 1; + MOperator newMop = AArch64isa::GetMopSub2Subs(lastInsn); Operand &rflag = GetOrCreateRflag(); std::vector opndVec; opndVec.push_back(&rflag); @@ -5324,10 +5455,17 @@ Operand *AArch64CGFunc::SelectAbs(UnaryNode &node, Operand &opnd0) /* promoted type */ PrimType primType = is64Bits ? (PTY_i64) : (PTY_i32); Operand &newOpnd0 = LoadIntoRegister(opnd0, primType); - Insn *lastInsn = GetCurBB()->GetLastInsn(); - if (lastInsn != nullptr && lastInsn->GetMachineOpcode() >= MOP_xsubrrr && - lastInsn->GetMachineOpcode() <= MOP_wsubrri12) { - return SelectAbsSub(*lastInsn, node, newOpnd0); + Insn *lastInsn = GetCurBB()->GetLastMachineInsn(); + if (lastInsn != nullptr && AArch64isa::IsSub(*lastInsn)) { + Operand &dest = lastInsn->GetOperand(kInsnFirstOpnd); + Operand &opd1 = lastInsn->GetOperand(kInsnSecondOpnd); + Operand &opd2 = lastInsn->GetOperand(kInsnThirdOpnd); + regno_t absReg = static_cast(newOpnd0).GetRegisterNumber(); + if ((dest.IsRegister() && static_cast(dest).GetRegisterNumber() == absReg) || + (opd1.IsRegister() && static_cast(opd1).GetRegisterNumber() == absReg) || + (opd2.IsRegister() && static_cast(opd2).GetRegisterNumber() == absReg)) { + return SelectAbsSub(*lastInsn, node, newOpnd0); + } } RegOperand &resOpnd = CreateRegisterOperandOfType(primType); SelectAArch64Cmp(newOpnd0, CreateImmOperand(0, is64Bits ? PTY_u64 : PTY_u32, false), true, @@ -5470,9 +5608,9 @@ Operand *AArch64CGFunc::SelectExtractbits(ExtractbitsNode &node, Operand &srcOpn /* * operand fits in MOVK if - * is64Bits && boffst == 0, 16, 32, 48 && bSize == 16, so boffset / 16 == 0, 1, 2, 3; (boffset / 16 ) & (~3) == 0 - * or is32Bits && boffset == 0, 16 && bSize == 16, so boffset / 16 == 0, 1; (boffset / 16) & (~1) == 0 - * imm range of aarch64-movk [0 - 65536] imm16 + * is64Bits && bitOffset == 0, 16, 32, 48 && bSize == 16 + * or is32Bits && bitOffset == 0, 16 && bSize == 16 + * imm range of aarch64-movk is [0 - 65536] imm16 */ inline bool IsMoveWideKeepable(int64 offsetVal, uint32 bitOffset, uint32 bitSize, bool is64Bits) { @@ -5481,8 +5619,12 @@ inline bool IsMoveWideKeepable(int64 offsetVal, uint32 bitOffset, uint32 bitSize if (!isOutOfRange) { isOutOfRange = (static_cast(offsetVal) >> k16BitSize) > 0; } - return (!isOutOfRange) && bitSize == k16BitSize && - ((bitOffset >> k16BitShift) & ~static_cast(is64Bits ? 0x3 : 0x1)) == 0; + if (isOutOfRange) { + return false; + } + return ((bitOffset == k0BitSize || bitOffset == k16BitSize) || + (is64Bits && (bitOffset == k32BitSize || bitOffset == k48BitSize))) && + bitSize == k16BitSize; } /* we use the fact that A ^ B ^ A == B, A ^ 0 = A */ @@ -6001,29 +6143,10 @@ void AArch64CGFunc::SelectCvtInt2Int(const BaseNode *parent, Operand *&resOpnd, GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(mOp, *resOpnd, *opnd0)); } else { /* Unsigned */ - if (is64Bit) { - if (fsize == k8BitSize) { - ImmOperand &immOpnd = CreateImmOperand(0xff, k64BitSize, false); - GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xandrri13, *resOpnd, *opnd0, immOpnd)); - } else if (fsize == k16BitSize) { - ImmOperand &immOpnd = CreateImmOperand(0xffff, k64BitSize, false); - GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xandrri13, *resOpnd, *opnd0, immOpnd)); - } else { - GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xuxtw64, *resOpnd, *opnd0)); - } - } else { - DEBUG_ASSERT(((fsize == k8BitSize) || (fsize == k16BitSize)), "incorrect from size"); - if (fsize == k8BitSize) { - static_cast(opnd0)->SetValidBitsNum(k8BitSize); - static_cast(resOpnd)->SetValidBitsNum(k8BitSize); - } - if (fromType == PTY_u1) { - static_cast(opnd0)->SetValidBitsNum(1); - static_cast(resOpnd)->SetValidBitsNum(1); - } - GetCurBB()->AppendInsn( - GetInsnBuilder()->BuildInsn((fsize == k8BitSize) ? MOP_xuxtb32 : MOP_xuxth32, *resOpnd, *opnd0)); - } + auto mOp = + (is64Bit ? ((fsize == k8BitSize) ? MOP_xuxtb32 : ((fsize == k16BitSize) ? MOP_xuxth32 : MOP_xuxtw64)) + : ((fsize == k8BitSize) ? MOP_xuxtb32 : MOP_xuxth32)); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(mOp, *resOpnd, LoadIntoRegister(*opnd0, fromType))); } } else { /* Same size or truncate */ #ifdef CNV_OPTIMIZE @@ -6229,7 +6352,7 @@ void AArch64CGFunc::SelectRangeGoto(RangeGotoNode &rangeGotoNode, Operand &srcOp * we store 8-byte displacement ( jump_label - offset_table_address ) * in the table. Refer to AArch64Emit::Emit() in aarch64emit.cpp */ - std::vector sizeArray; + std::vector sizeArray; sizeArray.emplace_back(switchTable.size()); MIRArrayType *arrayType = memPool->New(etype->GetTypeIndex(), sizeArray); MIRAggConst *arrayConst = memPool->New(mirModule, *arrayType); @@ -6516,8 +6639,8 @@ void AArch64CGFunc::ReplaceOpndInInsn(RegOperand ®Dest, RegOperand ®Src, I newMem->SetBaseRegister(regSrc); } if (indexRegOpnd != nullptr && indexRegOpnd->GetRegisterNumber() == destNO) { - auto *newRegSrc = static_cast(regSrc.Clone(*GetMemoryPool())); - newRegSrc->SetSize(indexRegOpnd->GetSize()); // retain the original size + auto *newRegSrc = static_cast(regSrc.Clone(*GetMemoryPool())); + newRegSrc->SetSize(indexRegOpnd->GetSize()); // retain the original size newMem->SetIndexRegister(*newRegSrc); } insn.SetMemOpnd(newMem); @@ -6530,6 +6653,7 @@ void AArch64CGFunc::ReplaceOpndInInsn(RegOperand ®Dest, RegOperand ®Src, I regSrc.SetBaseRefOpnd(*regOpnd.GetBaseRefOpnd()); ReplaceRegReference(regOpnd.GetRegisterNumber(), regSrc.GetRegisterNumber()); } + CHECK_FATAL(regOpnd.GetSize() == regSrc.GetSize(), "NIY"); insn.SetOperand(static_cast(i), regSrc); } if (regOpnd.GetBaseRefOpnd() != nullptr && regOpnd.GetBaseRefOpnd()->GetRegisterNumber() == destNO) { @@ -6543,7 +6667,7 @@ void AArch64CGFunc::ReplaceOpndInInsn(RegOperand ®Dest, RegOperand ®Src, I if (!opnd->IsRegister()) { continue; } - auto ®Opnd = static_cast(*opnd); + auto ®Opnd = static_cast(*opnd); if (regOpnd.GetRegisterNumber() == destNO) { insn.GetStackMap()->GetDeoptInfo().ReplaceDeoptBundleInfo(deoptVreg, regSrc); ReplaceRegReference(regOpnd.GetRegisterNumber(), regSrc.GetRegisterNumber()); @@ -6555,8 +6679,10 @@ void AArch64CGFunc::ReplaceOpndInInsn(RegOperand ®Dest, RegOperand ®Src, I void AArch64CGFunc::CleanupDeadMov(bool dumpInfo) { /* clean dead mov. */ - FOR_ALL_BB(bb, this) { - FOR_BB_INSNS_SAFE(insn, bb, ninsn) { + FOR_ALL_BB(bb, this) + { + FOR_BB_INSNS_SAFE(insn, bb, ninsn) + { if (!insn->IsMachineInstruction()) { continue; } @@ -7051,8 +7177,10 @@ void AArch64CGFunc::GenSaveMethodInfoCode(BB &bb) bool AArch64CGFunc::HasStackLoadStore() { - FOR_ALL_BB(bb, this) { - FOR_BB_INSNS(insn, bb) { + FOR_ALL_BB(bb, this) + { + FOR_BB_INSNS(insn, bb) + { uint32 opndNum = insn->GetOperandSize(); for (uint32 i = 0; i < opndNum; ++i) { Operand &opnd = insn->GetOperand(i); @@ -7877,6 +8005,9 @@ void AArch64CGFunc::SelectParmListIreadLargeAggregate(const IreadNode &iread, MI void AArch64CGFunc::CreateCallStructParamPassByStack(int32 symSize, const MIRSymbol *sym, RegOperand *addrOpnd, int32 baseOffset) { + if (symSize == 0) { + return; + } MemOperand *ldMopnd = nullptr; MemOperand *stMopnd = nullptr; uint32 numRegNeeded = (static_cast(symSize) <= k8ByteSize) ? kOneRegister : kTwoRegister; @@ -7925,10 +8056,10 @@ RegOperand *AArch64CGFunc::SelectParmListDreadAccessField(const MIRSymbol &sym, case 1: reg = static_cast(ploc.reg1); break; - case 2: // parmNum 2 use reg2 + case 2: // parmNum 2 use reg2 reg = static_cast(ploc.reg2); break; - case 3: // parmNum 3 use reg3 + case 3: // parmNum 3 use reg3 reg = static_cast(ploc.reg3); break; default: @@ -7954,10 +8085,21 @@ RegOperand *AArch64CGFunc::SelectParmListDreadAccessField(const MIRSymbol &sym, } MemOperand *memOpnd; if (sym.GetStorageClass() == kScFormal && fieldID > 0) { - MemOperand &baseOpnd = GetOrCreateMemOpnd(sym, 0, memSize); - RegOperand &base = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); - GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(PickLdInsn(k64BitSize, PTY_i64), base, baseOpnd)); - memOpnd = &CreateMemOpnd(base, (static_cast(offset) + parmNum * GetPointerSize()), memSize); + MIRType *ty = sym.GetType(); + uint64 symSize = GetBecommon().GetTypeSize(ty->GetTypeIndex().GetIdx()); + /* sym passed by address, need to be dereference */ + if (symSize > k16ByteSize) { + MemOperand &baseOpnd = GetOrCreateMemOpnd(sym, 0, memSize); + RegOperand &base = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(PickLdInsn(k64BitSize, PTY_i64), base, baseOpnd)); + memOpnd = &CreateMemOpnd(base, (static_cast(offset) + parmNum * GetPointerSize()), memSize); + } else { /* sym passed by register , no need to be dereference */ + if (CGOptions::IsArm64ilp32()) { + memOpnd = &GetOrCreateMemOpnd(sym, (k8ByteSize * parmNum + static_cast(offset)), memSize); + } else { + memOpnd = &GetOrCreateMemOpnd(sym, (GetPointerSize() * parmNum + static_cast(offset)), memSize); + } + } } else if (ploc.fpSize) { memOpnd = &GetOrCreateMemOpnd(sym, (ploc.fpSize * parmNum + static_cast(offset)), memSize); } else { @@ -8010,8 +8152,8 @@ void AArch64CGFunc::CreateCallStructParamPassByReg(regno_t regno, MemOperand &me srcOpnds.PushOpnd(*parmOpnd); } -void AArch64CGFunc::CreateCallStructParamMemcpy(const MIRSymbol *sym, RegOperand *addropnd, uint32 structSize, - int32 copyOffset, int32 fromOffset) +void AArch64CGFunc::CreateCallStructParamMemcpy(const MIRSymbol &sym, uint32 structSize, int32 copyOffset, + int32 fromOffset) { std::vector opndVec; @@ -8024,44 +8166,71 @@ void AArch64CGFunc::CreateCallStructParamMemcpy(const MIRSymbol *sym, RegOperand SelectAdd(*parmOpnd, *spReg, *offsetOpnd0, PTY_a64); opndVec.push_back(parmOpnd); /* param 0 */ - if (sym != nullptr) { - if (sym->GetStorageClass() == kScGlobal || sym->GetStorageClass() == kScExtern) { - StImmOperand &stopnd = CreateStImmOperand(*sym, fromOffset, 0); - RegOperand &staddropnd = static_cast(CreateRegisterOperandOfType(PTY_u64)); - SelectAddrof(staddropnd, stopnd); - opndVec.push_back(&staddropnd); /* param 1 */ - } else if (sym->GetStorageClass() == kScAuto || sym->GetStorageClass() == kScFormal) { - RegOperand *parm1Reg = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); - AArch64SymbolAlloc *symloc = - static_cast(GetMemlayout()->GetSymAllocInfo(sym->GetStIndex())); - RegOperand *baseOpnd = static_cast(GetBaseReg(*symloc)); - int32 stoffset = GetBaseOffset(*symloc); - ImmOperand *offsetOpnd1 = &CreateImmOperand(static_cast(stoffset), k64BitSize, false); - GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xaddrri12, *parm1Reg, *baseOpnd, *offsetOpnd1)); - if (sym->GetStorageClass() == kScFormal) { - MemOperand *ldmopnd = - &GetOrCreateMemOpnd(MemOperand::kAddrModeBOi, k64BitSize, parm1Reg, nullptr, - &GetOrCreateOfstOpnd(0, k32BitSize), static_cast(nullptr)); - RegOperand *tmpreg = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); - RegOperand *vreg2 = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); - GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(PickLdInsn(k64BitSize, PTY_a64), *tmpreg, *ldmopnd)); - GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xaddrri12, *vreg2, *tmpreg, - CreateImmOperand(fromOffset, k64BitSize, false))); - parm1Reg = vreg2; - } - opndVec.push_back(parm1Reg); /* param 1 */ - } else if (sym->GetStorageClass() == kScPstatic || sym->GetStorageClass() == kScFstatic) { - CHECK_FATAL(sym->GetSKind() != kStConst, "Unsupported sym const for struct param"); - StImmOperand *stopnd = &CreateStImmOperand(*sym, 0, 0); - RegOperand &staddropnd = static_cast(CreateRegisterOperandOfType(PTY_u64)); - GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xadrp, staddropnd, *stopnd)); - GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xadrpl12, staddropnd, staddropnd, *stopnd)); - opndVec.push_back(&staddropnd); /* param 1 */ - } else { - CHECK_FATAL(0, "Unsupported sym for struct param"); - } + if (sym.GetStorageClass() == kScGlobal || sym.GetStorageClass() == kScExtern) { + StImmOperand &stopnd = CreateStImmOperand(sym, fromOffset, 0); + RegOperand &staddropnd = static_cast(CreateRegisterOperandOfType(PTY_u64)); + SelectAddrof(staddropnd, stopnd); + opndVec.push_back(&staddropnd); /* param 1 */ + } else if (sym.GetStorageClass() == kScAuto || sym.GetStorageClass() == kScFormal) { + RegOperand *parm1Reg = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); + AArch64SymbolAlloc *symloc = + static_cast(GetMemlayout()->GetSymAllocInfo(sym.GetStIndex())); + RegOperand *baseOpnd = static_cast(GetBaseReg(*symloc)); + int32 stoffset = GetBaseOffset(*symloc); + ImmOperand *offsetOpnd1 = &CreateImmOperand(static_cast(stoffset), k64BitSize, false); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xaddrri12, *parm1Reg, *baseOpnd, *offsetOpnd1)); + if (sym.GetStorageClass() == kScFormal) { + MemOperand *ldmopnd = + &GetOrCreateMemOpnd(MemOperand::kAddrModeBOi, k64BitSize, parm1Reg, nullptr, + &GetOrCreateOfstOpnd(0, k32BitSize), static_cast(nullptr)); + RegOperand *tmpreg = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); + RegOperand *vreg2 = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(PickLdInsn(k64BitSize, PTY_a64), *tmpreg, *ldmopnd)); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xaddrri12, *vreg2, *tmpreg, + CreateImmOperand(fromOffset, k64BitSize, false))); + parm1Reg = vreg2; + } + opndVec.push_back(parm1Reg); /* param 1 */ + } else if (sym.GetStorageClass() == kScPstatic || sym.GetStorageClass() == kScFstatic) { + CHECK_FATAL(sym.GetSKind() != kStConst, "Unsupported sym const for struct param"); + StImmOperand *stopnd = &CreateStImmOperand(sym, 0, 0); + RegOperand &staddropnd = static_cast(CreateRegisterOperandOfType(PTY_u64)); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xadrp, staddropnd, *stopnd)); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xadrpl12, staddropnd, staddropnd, *stopnd)); + opndVec.push_back(&staddropnd); /* param 1 */ + } else { + CHECK_FATAL(false, "Unsupported sym for struct param"); + } + + RegOperand &vreg3 = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8BitSize)); + ImmOperand &sizeOpnd = CreateImmOperand(structSize, k64BitSize, false); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_wmovri32, vreg3, sizeOpnd)); + opndVec.push_back(&vreg3); /* param 2 */ + + SelectLibCall("memcpy", opndVec, PTY_a64, PTY_a64); +} + +void AArch64CGFunc::CreateCallStructParamMemcpy(RegOperand &addrOpnd, uint32 structSize, int32 copyOffset, + int32 fromOffset) +{ + std::vector opndVec; + + RegOperand *vreg1 = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8BitSize)); + opndVec.push_back(vreg1); /* result */ + + RegOperand *parmOpnd = &CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8BitSize)); + RegOperand *spReg = &GetOrCreatePhysicalRegisterOperand(RSP, k64BitSize, kRegTyInt); + ImmOperand *offsetOpnd0 = &CreateImmOperand(copyOffset, k64BitSize, false); + SelectAdd(*parmOpnd, *spReg, *offsetOpnd0, PTY_a64); + opndVec.push_back(parmOpnd); /* param 0 */ + + if (fromOffset) { + RegOperand &p1vreg = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); + ImmOperand &fromImm = CreateImmOperand(fromOffset, k64BitSize, true); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xaddrri12, p1vreg, addrOpnd, fromImm)); + opndVec.push_back(&p1vreg); /* param 1 */ } else { - opndVec.push_back(addropnd); /* param 1 */ + opndVec.push_back(&addrOpnd); /* param 1 */ } RegOperand &vreg3 = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8BitSize)); @@ -8264,7 +8433,7 @@ void AArch64CGFunc::SelectParmListPreprocessLargeStruct(BaseNode &argExpr, int32 } symSize = GetBecommon().GetTypeSize(ty->GetTypeIndex().GetIdx()); if (symSize > kParmMemcpySize) { - CreateCallStructParamMemcpy(sym, nullptr, static_cast(symSize), structCopyOffset, rhsOffset); + CreateCallStructParamMemcpy(*sym, static_cast(symSize), structCopyOffset, rhsOffset); structCopyOffset += static_cast(RoundUp(symSize, GetPointerSize())); } else if (symSize > k16ByteSize) { uint32 numMemOp = static_cast(RoundUp(symSize, GetPointerSize()) / GetPointerSize()); @@ -8292,7 +8461,7 @@ void AArch64CGFunc::SelectParmListPreprocessLargeStruct(BaseNode &argExpr, int32 addrOpnd = result; } - CreateCallStructParamMemcpy(nullptr, addrOpnd, static_cast(symSize), structCopyOffset, rhsOffset); + CreateCallStructParamMemcpy(*addrOpnd, static_cast(symSize), structCopyOffset, rhsOffset); structCopyOffset += static_cast(RoundUp(symSize, GetPointerSize())); } else if (symSize > k16ByteSize) { uint32 numMemOp = static_cast(RoundUp(symSize, GetPointerSize()) / GetPointerSize()); @@ -8933,53 +9102,6 @@ void AArch64CGFunc::IntrinsifyStringIndexOf(ListOperand &srcOpnds, const MIRSymb SetCurBB(*jointBB); } -/* Lmbc calls have no argument, they are all explicit iassignspoff or - blkassign. Info collected and to be emitted here */ -void AArch64CGFunc::LmbcSelectParmList(ListOperand *srcOpnds, bool isArgReturn) -{ - if (GetLmbcArgInfo() == nullptr) { - return; /* no arg */ - } - CHECK_FATAL(GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc, "To be called for Lmbc model only"); - MapleVector &args = GetLmbcCallArgs(); - MapleVector &types = GetLmbcCallArgTypes(); - MapleVector &offsets = GetLmbcCallArgOffsets(); - MapleVector ®s = GetLmbcCallArgNumOfRegs(); - int iCnt = 0; - int fCnt = 0; - for (size_t i = isArgReturn ? 1 : 0; i < args.size(); i++) { - RegType ty = args[i]->GetRegisterType(); - PrimType pTy = types[i]; - AArch64reg reg; - if (args[i]->IsOfIntClass() && (iCnt + regs[i]) <= static_cast(k8ByteSize)) { - reg = static_cast(R0 + iCnt++); - RegOperand *res = &GetOrCreatePhysicalRegisterOperand(reg, GetPrimTypeSize(pTy) * kBitsPerByte, ty); - SelectCopy(*res, pTy, *args[i], pTy); - srcOpnds->PushOpnd(*res); - } else if (!args[i]->IsOfIntClass() && (fCnt + regs[i]) <= static_cast(k8ByteSize)) { - reg = static_cast(V0 + fCnt++); - RegOperand *res = &GetOrCreatePhysicalRegisterOperand(reg, GetPrimTypeSize(pTy) * kBitsPerByte, ty); - SelectCopy(*res, pTy, *args[i], pTy); - srcOpnds->PushOpnd(*res); - } else { - uint32 pSize = GetPrimTypeSize(pTy); - Operand &memOpd = CreateMemOpnd(RSP, offsets[i], pSize); - GetCurBB()->AppendInsn( - GetInsnBuilder()->BuildInsn(PickStInsn(pSize * kBitsPerByte, pTy), *args[i], memOpd)); - } - } - /* Load x8 if 1st arg is for agg return */ - if (isArgReturn) { - AArch64reg reg = static_cast(R8); - RegOperand *res = &GetOrCreatePhysicalRegisterOperand(reg, GetPrimTypeSize(PTY_a64) * kBitsPerByte, kRegTyInt); - SelectCopy(*res, PTY_a64, *args[0], PTY_a64); - srcOpnds->PushOpnd(*res); - } - ResetLmbcArgInfo(); /* reset */ - ResetLmbcArgsInRegs(); - ResetLmbcTotalArgs(); -} - void AArch64CGFunc::SelectCall(CallNode &callNode) { MIRFunction *fn = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(callNode.GetPUIdx()); @@ -8994,18 +9116,15 @@ void AArch64CGFunc::SelectCall(CallNode &callNode) ListOperand *srcOpnds = CreateListOpnd(*GetFuncScopeAllocator()); if (GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) { SetLmbcCallReturnType(nullptr); - bool largeStructRet = false; if (fn->IsFirstArgReturn()) { MIRPtrType *ptrTy = static_cast( GlobalTables::GetTypeTable().GetTypeFromTyIdx(fn->GetFormalDefVec()[0].formalTyIdx)); MIRType *sTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(ptrTy->GetPointedTyIdx()); - largeStructRet = sTy->GetSize() > k16ByteSize; SetLmbcCallReturnType(sTy); } else { MIRType *ty = fn->GetReturnType(); SetLmbcCallReturnType(ty); } - LmbcSelectParmList(srcOpnds, largeStructRet); } SelectParmListWrapper(callNode, *srcOpnds, false); @@ -9033,7 +9152,7 @@ void AArch64CGFunc::SelectCall(CallNode &callNode) CHECK_FATAL(opnd != nullptr, "pregIdx has not been assigned Operand"); callInsn.AddDeoptBundleInfo(elem.first, *opnd); } else if (valueKind == MapleValue::kConstKind) { - auto *opnd = SelectIntConst(static_cast(elem.second.GetConstValue())); + auto *opnd = SelectIntConst(static_cast(elem.second.GetConstValue()), callNode); callInsn.AddDeoptBundleInfo(elem.first, *opnd); } else { CHECK_FATAL(false, "not supported currently"); @@ -9056,15 +9175,16 @@ void AArch64CGFunc::SelectCall(CallNode &callNode) } } -void AArch64CGFunc::SelectIcall(IcallNode &icallNode, Operand &srcOpnd) +void AArch64CGFunc::SelectIcall(IcallNode &icallNode) { ListOperand *srcOpnds = CreateListOpnd(*GetFuncScopeAllocator()); SelectParmListWrapper(icallNode, *srcOpnds, false); - Operand *fptrOpnd = &srcOpnd; + Operand *srcOpnd = HandleExpr(icallNode, *icallNode.GetNopndAt(0)); + Operand *fptrOpnd = srcOpnd; if (fptrOpnd->GetKind() != Operand::kOpdRegister) { PrimType ty = icallNode.Opnd(0)->GetPrimType(); - fptrOpnd = &SelectCopy(srcOpnd, ty, ty); + fptrOpnd = &SelectCopy(*srcOpnd, ty, ty); } DEBUG_ASSERT(fptrOpnd->IsRegister(), "SelectIcall: function pointer not RegOperand"); RegOperand *regOpnd = static_cast(fptrOpnd); @@ -9088,7 +9208,7 @@ void AArch64CGFunc::SelectIcall(IcallNode &icallNode, Operand &srcOpnd) GetCurBB()->AppendInsn(callInsn); GetCurBB()->SetHasCall(); - DEBUG_ASSERT(GetCurBB()->GetLastInsn()->IsCall(), "lastInsn should be a call"); + DEBUG_ASSERT(GetCurBB()->GetLastMachineInsn()->IsCall(), "lastInsn should be a call"); GetFunction().SetHasCall(); const auto &deoptBundleInfo = icallNode.GetDeoptBundleInfo(); for (const auto &elem : deoptBundleInfo) { @@ -9098,7 +9218,7 @@ void AArch64CGFunc::SelectIcall(IcallNode &icallNode, Operand &srcOpnd) CHECK_FATAL(opnd != nullptr, "pregIdx has not been assigned Operand"); callInsn.AddDeoptBundleInfo(elem.first, *opnd); } else if (valueKind == MapleValue::kConstKind) { - auto *opnd = SelectIntConst(static_cast(elem.second.GetConstValue())); + auto *opnd = SelectIntConst(static_cast(elem.second.GetConstValue()), icallNode); callInsn.AddDeoptBundleInfo(elem.first, *opnd); } else { CHECK_FATAL(false, "not supported currently"); @@ -9197,11 +9317,9 @@ RegOperand &AArch64CGFunc::GetOrCreateSpecialRegisterOperand(PregIdx sregIdx, Pr AArch64reg reg = R0; switch (sregIdx) { case kSregSp: - reg = RSP; - break; + return GetOrCreatePhysicalRegisterOperand(RSP, k64BitSize, kRegTyInt); case kSregFp: - reg = RFP; - break; + return GetOrCreatePhysicalRegisterOperand(RFP, k64BitSize, kRegTyInt); case kSregGp: { MIRSymbol *sym = GetCG()->GetGP(); if (sym == nullptr) { @@ -9330,8 +9448,7 @@ LabelOperand &AArch64CGFunc::GetOrCreateLabelOperand(LabelIdx labIdx) if (it != hashLabelOpndTable.end()) { return *(it->second); } - const char *funcName = GetShortFuncName().c_str(); - LabelOperand *res = memPool->New(funcName, labIdx); + LabelOperand *res = memPool->New(GetShortFuncName().c_str(), labIdx, *memPool); hashLabelOpndTable[labIdx] = res; return *res; } @@ -9532,36 +9649,51 @@ MemOperand &AArch64CGFunc::GetOrCreateMemOpnd(const MIRSymbol &symbol, int64 off return *CreateMemOperand(MemOperand::kAddrModeBOi, size, stAddrOpnd, nullptr, &GetOrCreateOfstOpnd(0, k32BitSize), &symbol); } else if ((storageClass == kScPstatic) || (storageClass == kScFstatic)) { - if (symbol.GetSKind() == kStConst) { - DEBUG_ASSERT(offset == 0, "offset should be 0 for constant literals"); - return *CreateMemOperand(MemOperand::kAddrModeLiteral, size, symbol); + return CreateMemOpndForStatic(symbol, offset, size, needLow12, regOp); + } else { + CHECK_FATAL(false, "NYI"); + } +} + +MemOperand &AArch64CGFunc::CreateMemOpndForStatic(const MIRSymbol &symbol, int64 offset, uint32 size, bool needLow12, + RegOperand *regOp) +{ + if (symbol.GetSKind() == kStConst) { + DEBUG_ASSERT(offset == 0, "offset should be 0 for constant literals"); + return *CreateMemOperand(MemOperand::kAddrModeLiteral, size, symbol); + } else { + /* not guaranteed align for uninitialized symbol */ + if (needLow12 || (!symbol.IsConst() && CGOptions::IsPIC())) { + StImmOperand &stOpnd = CreateStImmOperand(symbol, offset, 0); + if (!regOp) { + regOp = static_cast(&CreateRegisterOperandOfType(PTY_u64)); + } + RegOperand &stAddrOpnd = *regOp; + SelectAddrof(stAddrOpnd, stOpnd); + return *CreateMemOperand(MemOperand::kAddrModeBOi, size, stAddrOpnd, nullptr, + &GetOrCreateOfstOpnd(0, k32BitSize), &symbol); } else { - /* not guaranteed align for uninitialized symbol */ - if (needLow12 || (!symbol.IsConst() && CGOptions::IsPIC())) { - StImmOperand &stOpnd = CreateStImmOperand(symbol, offset, 0); - if (!regOp) { - regOp = static_cast(&CreateRegisterOperandOfType(PTY_u64)); - } - RegOperand &stAddrOpnd = *regOp; - SelectAddrof(stAddrOpnd, stOpnd); + StImmOperand &stOpnd = CreateStImmOperand(symbol, offset, 0); + if (!regOp) { + regOp = static_cast(&CreateRegisterOperandOfType(PTY_u64)); + } + RegOperand &stAddrOpnd = *regOp; + /* adrp x1, _PTR__cinf_Ljava_2Flang_2FSystem_3B */ + Insn &insn = GetInsnBuilder()->BuildInsn(MOP_xadrp, stAddrOpnd, stOpnd); + GetCurBB()->AppendInsn(insn); + if (GetCG()->GetOptimizeLevel() == CGOptions::kLevel0 || + ((size == k64BitSize) && (offset % static_cast(k8BitSizeInt) != 0)) || + ((size == k32BitSize) && (offset % static_cast(k4BitSizeInt) != 0)) || + ((size == k16BitSize) && (offset % static_cast(k2BitSizeInt) != 0))) { + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_xadrpl12, stAddrOpnd, stAddrOpnd, stOpnd)); return *CreateMemOperand(MemOperand::kAddrModeBOi, size, stAddrOpnd, nullptr, - &GetOrCreateOfstOpnd(0, k32BitSize), &symbol); - } else { - StImmOperand &stOpnd = CreateStImmOperand(symbol, offset, 0); - if (!regOp) { - regOp = static_cast(&CreateRegisterOperandOfType(PTY_u64)); - } - RegOperand &stAddrOpnd = *regOp; - /* adrp x1, _PTR__cinf_Ljava_2Flang_2FSystem_3B */ - Insn &insn = GetInsnBuilder()->BuildInsn(MOP_xadrp, stAddrOpnd, stOpnd); - GetCurBB()->AppendInsn(insn); - /* ldr x1, [x1, #:lo12:_PTR__cinf_Ljava_2Flang_2FSystem_3B] */ - return *CreateMemOperand(MemOperand::kAddrModeLo12Li, size, stAddrOpnd, nullptr, - &GetOrCreateOfstOpnd(static_cast(offset), k32BitSize), &symbol); + &GetOrCreateOfstOpnd(static_cast(0), k32BitSize), nullptr); } + + /* ldr x1, [x1, #:lo12:_PTR__cinf_Ljava_2Flang_2FSystem_3B] */ + return *CreateMemOperand(MemOperand::kAddrModeLo12Li, size, stAddrOpnd, nullptr, + &GetOrCreateOfstOpnd(static_cast(offset), k32BitSize), &symbol); } - } else { - CHECK_FATAL(false, "NYI"); } } @@ -9627,7 +9759,7 @@ MemOperand &AArch64CGFunc::CreateMemOpnd(RegOperand &baseOpnd, int64 offset, uin } RegOperand &AArch64CGFunc::GenStructParamIndex(RegOperand &base, const BaseNode &indexExpr, int shift, - PrimType baseType, PrimType targetType) + PrimType baseType) { RegOperand *index = &LoadIntoRegister(*HandleExpr(indexExpr, *(indexExpr.Opnd(0))), PTY_a64); RegOperand *srcOpnd = &CreateRegisterOperandOfType(PTY_a64); @@ -9640,7 +9772,7 @@ RegOperand &AArch64CGFunc::GenStructParamIndex(RegOperand &base, const BaseNode MemOperand &mo = GetOrCreateMemOpnd(MemOperand::kAddrModeBOi, k64BitSize, result, nullptr, offopnd, nullptr); RegOperand &structAddr = CreateVirtualRegisterOperand(NewVReg(kRegTyInt, k8ByteSize)); GetCurBB()->AppendInsn( - GetInsnBuilder()->BuildInsn(PickLdInsn(GetPrimTypeBitSize(baseType), targetType), structAddr, mo)); + GetInsnBuilder()->BuildInsn(PickLdInsn(GetPrimTypeBitSize(baseType), baseType), structAddr, mo)); return structAddr; } @@ -9695,6 +9827,9 @@ MemOperand *AArch64CGFunc::CheckAndCreateExtendMemOpnd(PrimType ptype, const Bas auto *indexReg = SelectRegread(*static_cast(addendExpr)); MemOperand *memOpnd = &GetOrCreateMemOpnd(MemOperand::kAddrModeBOrX, GetPrimTypeBitSize(ptype), baseReg, indexReg, nullptr, nullptr); + if (CGOptions::IsArm64ilp32() && IsSignedInteger(addendExpr->GetPrimType())) { + memOpnd->SetExtend(memOpnd->GetExtend() | MemOperand::ExtendInfo::kSignExtend); + } return memOpnd; /* case 4 */ } else if (addendExpr->GetOpCode() == OP_cvt && addendExpr->GetNumOpnds() == 1) { @@ -9744,7 +9879,7 @@ MemOperand *AArch64CGFunc::CheckAndCreateExtendMemOpnd(PrimType ptype, const Bas PrimType fromType = typeCvtNode->FromType(); PrimType toType = typeCvtNode->GetPrimType(); if (isAggParamInReg) { - aggParamReg = &GenStructParamIndex(base, *indexExpr, shift, ptype, fromType); + aggParamReg = &GenStructParamIndex(base, *indexExpr, shift, ptype); return nullptr; } MemOperand *memOpnd = nullptr; @@ -9777,7 +9912,7 @@ MemOperand &AArch64CGFunc::CreateNonExtendMemOpnd(PrimType ptype, const BaseNode addrOpnd = HandleExpr(parent, addrExpr); } addrOpnd = static_cast(&LoadIntoRegister(*addrOpnd, PTY_a64)); - Insn *lastInsn = GetCurBB() == nullptr ? nullptr : GetCurBB()->GetLastInsn(); + Insn *lastInsn = GetCurBB() == nullptr ? nullptr : GetCurBB()->GetLastMachineInsn(); if ((addrExpr.GetOpCode() == OP_CG_array_elem_add) && (offset == 0) && lastInsn && (lastInsn->GetMachineOpcode() == MOP_xadrpl12) && (&lastInsn->GetOperand(kInsnFirstOpnd) == &lastInsn->GetOperand(kInsnSecondOpnd))) { @@ -9788,7 +9923,9 @@ MemOperand &AArch64CGFunc::CreateNonExtendMemOpnd(PrimType ptype, const BaseNode MemOperand &tmpMemOpnd = GetOrCreateMemOpnd(MemOperand::kAddrModeLo12Li, GetPrimTypeBitSize(ptype), static_cast(addrOpnd), nullptr, &ofstOpnd, stOpnd.GetSymbol()); - GetCurBB()->RemoveInsn(*GetCurBB()->GetLastInsn()); + if (GetCurBB() && GetCurBB()->GetLastMachineInsn()) { + GetCurBB()->RemoveInsn(*GetCurBB()->GetLastMachineInsn()); + } return tmpMemOpnd; } else { OfstOperand &ofstOpnd = GetOrCreateOfstOpnd(static_cast(offset), k64BitSize); @@ -9958,34 +10095,54 @@ Operand *AArch64CGFunc::GetBaseReg(const AArch64SymbolAlloc &symAlloc) return fsp; } -int32 AArch64CGFunc::GetBaseOffset(const SymbolAlloc &sa) +int32 AArch64CGFunc::GetBaseOffset(const SymbolAlloc &symbolAlloc) { - const AArch64SymbolAlloc *symAlloc = static_cast(&sa); - /* Call Frame layout of AArch64 - * Refer to V2 in aarch64_memlayout.h. - * Do Not change this unless you know what you do - */ - const int32 sizeofFplr = 2 * kIntregBytelen; + const AArch64SymbolAlloc *symAlloc = static_cast(&symbolAlloc); + // Call Frame layout of AArch64 + // Refer to V2 in aarch64_memlayout.h. + // Do Not change this unless you know what you do + // O2 mode refer to V2.1 in aarch64_memlayout.cpp + const int32 sizeofFplr = static_cast(2 * kIntregBytelen); MemSegmentKind sgKind = symAlloc->GetMemSegment()->GetMemSegmentKind(); AArch64MemLayout *memLayout = static_cast(this->GetMemlayout()); if (sgKind == kMsArgsStkPassed) { /* for callees */ int32 offset = static_cast(symAlloc->GetOffset()); + offset += static_cast(memLayout->GetSizeOfColdToStk()); + return offset; + } else if (sgKind == kMsCold) { + int offset = static_cast(symAlloc->GetOffset()); return offset; } else if (sgKind == kMsArgsRegPassed) { - int32 baseOffset = memLayout->GetSizeOfLocals() + symAlloc->GetOffset() + memLayout->GetSizeOfRefLocals(); + int32 baseOffset; + if (GetCG()->IsLmbc()) { + baseOffset = static_cast(symAlloc->GetOffset()) + + static_cast(memLayout->GetSizeOfRefLocals() + + memLayout->SizeOfArgsToStackPass()); /* SP relative */ + } else { + baseOffset = static_cast(memLayout->GetSizeOfLocals() + memLayout->GetSizeOfRefLocals()) + + static_cast(symAlloc->GetOffset()); + } return baseOffset + sizeofFplr; } else if (sgKind == kMsRefLocals) { - int32 baseOffset = symAlloc->GetOffset() + memLayout->GetSizeOfLocals(); + int32 baseOffset = static_cast(symAlloc->GetOffset()) + static_cast(memLayout->GetSizeOfLocals()); return baseOffset + sizeofFplr; } else if (sgKind == kMsLocals) { + if (GetCG()->IsLmbc()) { + CHECK_FATAL(false, "invalid lmbc's locals"); + } int32 baseOffset = symAlloc->GetOffset(); return baseOffset + sizeofFplr; } else if (sgKind == kMsSpillReg) { + int32 baseOffset; if (GetCG()->IsLmbc()) { - return symAlloc->GetOffset() + memLayout->SizeOfArgsToStackPass(); + baseOffset = static_cast(symAlloc->GetOffset()) + + static_cast(memLayout->SizeOfArgsRegisterPassed() + memLayout->GetSizeOfRefLocals() + + memLayout->SizeOfArgsToStackPass()); + } else { + baseOffset = static_cast(symAlloc->GetOffset()) + + static_cast(memLayout->SizeOfArgsRegisterPassed() + memLayout->GetSizeOfLocals() + + memLayout->GetSizeOfRefLocals()); } - int32 baseOffset = symAlloc->GetOffset() + memLayout->SizeOfArgsRegisterPassed() + - memLayout->GetSizeOfLocals() + memLayout->GetSizeOfRefLocals(); return baseOffset + sizeofFplr; } else if (sgKind == kMsArgsToStkPass) { /* this is for callers */ return static_cast(symAlloc->GetOffset()); @@ -10003,7 +10160,16 @@ void AArch64CGFunc::AppendCall(const MIRSymbol &funcSymbol) void AArch64CGFunc::DBGFixCallFrameLocationOffsets() { - for (DBGExprLoc *el : GetDbgCallFrameLocations()) { + unsigned idx = 0; + for (DBGExprLoc *el : GetDbgCallFrameLocations(true)) { + if (el && el->GetSimpLoc() && el->GetSimpLoc()->GetDwOp() == DW_OP_fbreg) { + SymbolAlloc *symloc = static_cast(el->GetSymLoc()); + int32 offset = GetBaseOffset(*symloc) - ((idx < AArch64Abi::kNumIntParmRegs) ? GetDbgCallFrameOffset() : 0); + el->SetFboffset(offset); + } + idx++; + } + for (DBGExprLoc *el : GetDbgCallFrameLocations(false)) { if (el->GetSimpLoc()->GetDwOp() == DW_OP_fbreg) { SymbolAlloc *symloc = static_cast(el->GetSymLoc()); int32 offset = GetBaseOffset(*symloc) - GetDbgCallFrameOffset(); @@ -10136,13 +10302,12 @@ MemOperand *AArch64CGFunc::GetOrCreatSpillMem(regno_t vrNum, uint32 memSize) if (vrNum >= vRegTable.size()) { CHECK_FATAL(false, "index out of range in AArch64CGFunc::FreeSpillRegMem"); } - uint32 memBitSize = (memSize <= k32BitSize) ? k32BitSize : - (memSize <= k64BitSize) ? k64BitSize : k128BitSize; + uint32 memBitSize = (memSize <= k32BitSize) ? k32BitSize : (memSize <= k64BitSize) ? k64BitSize : k128BitSize; auto it = reuseSpillLocMem.find(memBitSize); if (it != reuseSpillLocMem.end()) { MemOperand *memOpnd = it->second->GetOne(); if (memOpnd != nullptr) { - (void)spillRegMemOperands.emplace(std::pair(vrNum, memOpnd)); + (void)spillRegMemOperands.emplace(std::pair(vrNum, memOpnd)); return memOpnd; } } @@ -10152,7 +10317,7 @@ MemOperand *AArch64CGFunc::GetOrCreatSpillMem(regno_t vrNum, uint32 memSize) MemOperand *memOpnd = nullptr; OfstOperand *offsetOpnd = &CreateOfstOpnd(static_cast(offset), k64BitSize); memOpnd = CreateMemOperand(MemOperand::kAddrModeBOi, memBitSize, baseOpnd, nullptr, offsetOpnd, nullptr); - (void)spillRegMemOperands.emplace(std::pair(vrNum, memOpnd)); + (void)spillRegMemOperands.emplace(std::pair(vrNum, memOpnd)); return memOpnd; } else { return p->second; @@ -10232,8 +10397,10 @@ bool AArch64CGFunc::CanLazyBinding(const Insn &ldrInsn) const */ void AArch64CGFunc::ConvertAdrpl12LdrToLdr() { - FOR_ALL_BB(bb, this) { - FOR_BB_INSNS_SAFE(insn, bb, nextInsn) { + FOR_ALL_BB(bb, this) + { + FOR_BB_INSNS_SAFE(insn, bb, nextInsn) + { nextInsn = insn->GetNextMachineInsn(); if (nextInsn == nullptr) { break; @@ -10297,8 +10464,10 @@ void AArch64CGFunc::ConvertAdrpl12LdrToLdr() */ void AArch64CGFunc::ConvertAdrpLdrToIntrisic() { - FOR_ALL_BB(bb, this) { - FOR_BB_INSNS_SAFE(insn, bb, nextInsn) { + FOR_ALL_BB(bb, this) + { + FOR_BB_INSNS_SAFE(insn, bb, nextInsn) + { nextInsn = insn->GetNextMachineInsn(); if (nextInsn == nullptr) { break; @@ -10631,7 +10800,7 @@ void AArch64CGFunc::GenCVaStartIntrin(RegOperand &opnd, uint32 stkSize) void AArch64CGFunc::SelectCVaStart(const IntrinsiccallNode &intrnNode) { - DEBUG_ASSERT(intrnNode.NumOpnds() == 2, "must be 2 operands"); // must be 2 operands + DEBUG_ASSERT(intrnNode.NumOpnds() == 2, "must be 2 operands"); // must be 2 operands /* 2 operands, but only 1 needed. Don't need to emit code for second operand * * va_list is a passed struct with an address, load its address @@ -10687,7 +10856,7 @@ void AArch64CGFunc::SelectCVaStart(const IntrinsiccallNode &intrnNode) // cset w4, ne void AArch64CGFunc::SelectOverFlowCall(const IntrinsiccallNode &intrnNode) { - DEBUG_ASSERT(intrnNode.NumOpnds() == 2, "must be 2 operands"); // must be 2 operands + DEBUG_ASSERT(intrnNode.NumOpnds() == 2, "must be 2 operands"); // must be 2 operands MIRIntrinsicID intrinsic = intrnNode.GetIntrinsic(); PrimType type = intrnNode.Opnd(0)->GetPrimType(); PrimType type2 = intrnNode.Opnd(1)->GetPrimType(); @@ -10721,7 +10890,7 @@ void AArch64CGFunc::SelectOverFlowCall(const IntrinsiccallNode &intrnNode) // store back auto *retVals = &intrnNode.GetReturnVec(); auto &pair = retVals->at(0); - stIdx2OverflowResult[pair.first] = std::pair(&resReg, &resReg2); + stIdx2OverflowResult[pair.first] = std::pair(&resReg, &resReg2); return; } @@ -10735,12 +10904,15 @@ void AArch64CGFunc::SelectOverFlowCall(const IntrinsiccallNode &intrnNode) */ void AArch64CGFunc::SelectCAtomicStoreN(const IntrinsiccallNode &intrinsiccallNode) { - auto primType = intrinsiccallNode.Opnd(1)->GetPrimType(); + auto primType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(intrinsiccallNode.GetTyIdx())->GetPrimType(); auto *addr = HandleExpr(intrinsiccallNode, *intrinsiccallNode.Opnd(0)); auto *value = HandleExpr(intrinsiccallNode, *intrinsiccallNode.Opnd(1)); auto *memOrderOpnd = intrinsiccallNode.Opnd(kInsnThirdOpnd); - auto *memOrderConst = static_cast(static_cast(memOrderOpnd)->GetConstVal()); - auto memOrder = static_cast(memOrderConst->GetExtValue()); + std::memory_order memOrder = std::memory_order_seq_cst; + if (memOrderOpnd->IsConstval()) { + auto *memOrderConst = static_cast(static_cast(memOrderOpnd)->GetConstVal()); + memOrder = static_cast(memOrderConst->GetExtValue()); + } SelectAtomicStore(*value, *addr, primType, PickMemOrder(memOrder, false)); } @@ -10788,7 +10960,7 @@ void AArch64CGFunc::SelectCTlsGlobalDesc(Operand &result, StImmOperand &stImm) SelectAdd(result, r0opnd, *specialFunc, PTY_u64); } -void AArch64CGFunc::SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) +void AArch64CGFunc::SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) { MIRIntrinsicID intrinsic = intrinsiccallNode.GetIntrinsic(); @@ -10856,6 +11028,9 @@ void AArch64CGFunc::SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) return; case INTRN_C_stack_restore: return; + case INTRN_C___builtin_division_exception: + SelectCDIVException(); + return; default: break; } @@ -10941,6 +11116,13 @@ void AArch64CGFunc::SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) IntrinsifyCompareAndSwapInt(*srcOpnds, PTY_i64); break; } + case INTRN_C___atomic_exchange_n: { + Operand *oldVal = SelectCAtomicExchangeN(intrinsiccallNode); + auto primType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(intrinsiccallNode.GetTyIdx())->GetPrimType(); + uint32 regSize = GetPrimTypeBitSize(primType); + SelectCopy(GetOrCreatePhysicalRegisterOperand(R0, regSize, kRegTyInt), primType, *oldVal, primType); + break; + } default: { CHECK_FATAL(false, "Intrinsic %d: %s not implemented by the AArch64 CG.", intrinsic, GetIntrinsicName(intrinsic)); @@ -11171,30 +11353,45 @@ Operand *AArch64CGFunc::SelectAArch64CSyncFetch(const IntrinsicopNode &intrinopN Operand *AArch64CGFunc::SelectCSyncCmpSwap(const IntrinsicopNode &intrinopNode, bool retBool) { PrimType primType = intrinopNode.GetNopndAt(kInsnSecondOpnd)->GetPrimType(); - DEBUG_ASSERT(primType == intrinopNode.GetNopndAt(kInsnThirdOpnd)->GetPrimType(), "gcc built_in rule"); LabelIdx atomicBBLabIdx = CreateLabel(); + /* Create BB which includes atomic built_in function */ BB *atomicBB = CreateNewBB(); atomicBB->SetKind(BB::kBBIf); atomicBB->SetAtomicBuiltIn(); atomicBB->AddLabel(atomicBBLabIdx); SetLab2BBMap(static_cast(atomicBBLabIdx), *atomicBB); GetCurBB()->AppendBB(*atomicBB); + /* keep variables inside same BB in O0 to avoid obtaining parameter value across BB blocks */ if (GetCG()->GetOptimizeLevel() == CGOptions::kLevel0) { SetCurBB(*atomicBB); } /* handle built_in args */ Operand *addrOpnd = HandleExpr(intrinopNode, *intrinopNode.GetNopndAt(kInsnFirstOpnd)); Operand *oldVal = HandleExpr(intrinopNode, *intrinopNode.GetNopndAt(kInsnSecondOpnd)); + + PrimType nodePrimType = intrinopNode.GetPrimType(); + uint32 nodePrimTypeSize = GetPrimTypeSize(nodePrimType); + // ensure the value is not changed after loading with extention + if (IsSignedInteger(nodePrimType) && nodePrimTypeSize < k4ByteSize && GetCurBB() && + GetCurBB()->GetLastMachineInsn() && GetCurBB()->GetLastMachineInsn()->IsLoad()) { + int64 maxIntVal = nodePrimTypeSize == k1ByteSize ? kMax8UnsignedImm : kMax16UnsignedImm; + Operand &lastDestOpnd = GetCurBB()->GetLastMachineInsn()->GetOperand(kInsnFirstOpnd); + DEBUG_ASSERT(lastDestOpnd.IsRegister(), "last insn's 1st operand is not register."); + ImmOperand &immOpnd = CreateImmOperand(primType, maxIntVal); + Insn &andInsn = GetInsnBuilder()->BuildInsn(MOP_wandrri12, lastDestOpnd, lastDestOpnd, immOpnd); + GetCurBB()->AppendInsn(andInsn); + } + Operand *newVal = HandleExpr(intrinopNode, *intrinopNode.GetNopndAt(kInsnThirdOpnd)); if (GetCG()->GetOptimizeLevel() != CGOptions::kLevel0) { SetCurBB(*atomicBB); } - uint32 primTypeP2Size = GetPrimTypeP2Size(primType); + uint32 nodePrimTypeP2Size = GetPrimTypeP2Size(nodePrimType); /* ldxr */ auto *regLoaded = &CreateRegisterOperandOfType(primType); auto &memOpnd = CreateMemOpnd(LoadIntoRegister(*addrOpnd, primType), 0, GetPrimTypeBitSize(primType)); - auto mOpLoad = PickLoadStoreExclInsn(primTypeP2Size, false, false); + auto mOpLoad = PickLoadStoreExclInsn(nodePrimTypeP2Size, false, false); atomicBB->AppendInsn(GetInsnBuilder()->BuildInsn(mOpLoad, *regLoaded, memOpnd)); Operand *regExtend = &CreateRegisterOperandOfType(primType); PrimType targetType = (oldVal->GetSize() <= k32BitSize) ? (IsSignedInteger(primType) ? PTY_i32 : PTY_u32) @@ -11214,7 +11411,7 @@ Operand *AArch64CGFunc::SelectCSyncCmpSwap(const IntrinsicopNode &intrinopNode, SetCurBB(*stlxrBB); auto *accessStatus = &CreateRegisterOperandOfType(PTY_u32); auto &newRegVal = LoadIntoRegister(*newVal, primType); - auto mOpStore = PickLoadStoreExclInsn(primTypeP2Size, true, true); + auto mOpStore = PickLoadStoreExclInsn(nodePrimTypeP2Size, true, true); stlxrBB->AppendInsn(GetInsnBuilder()->BuildInsn(mOpStore, *accessStatus, newRegVal, memOpnd)); /* cbnz ==> check the exclusive accsess status */ auto &atomicBBOpnd = GetOrCreateLabelOperand(*atomicBB); @@ -11223,6 +11420,11 @@ Operand *AArch64CGFunc::SelectCSyncCmpSwap(const IntrinsicopNode &intrinopNode, BB *nextBB = CreateNewBB(); nextBB->AddLabel(nextBBLableIdx); nextBB->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_dmb_ish, AArch64CG::kMd[MOP_dmb_ish])); + /* special handle for boolean return type */ + if (intrinopNode.GetPrimType() == PTY_u1) { + nextBB->AppendInsn( + GetInsnBuilder()->BuildInsn(MOP_wandrri12, *regLoaded, *regLoaded, CreateImmOperand(PTY_u32, 1))); + } SetLab2BBMap(static_cast(nextBBLableIdx), *nextBB); stlxrBB->AppendBB(*nextBB); SetCurBB(*nextBB); @@ -11254,6 +11456,7 @@ Operand *AArch64CGFunc::SelectCSyncValCmpSwap(IntrinsicopNode &intrinopNode) Operand *AArch64CGFunc::SelectCSyncLockTestSet(IntrinsicopNode &intrinopNode, PrimType pty) { auto primType = intrinopNode.GetPrimType(); + /*handle builtin args */ Operand *addrOpnd = HandleExpr(intrinopNode, *intrinopNode.GetNopndAt(kInsnFirstOpnd)); Operand *valueOpnd = HandleExpr(intrinopNode, *intrinopNode.GetNopndAt(kInsnSecondOpnd)); addrOpnd = &LoadIntoRegister(*addrOpnd, intrinopNode.GetNopndAt(kInsnFirstOpnd)->GetPrimType()); @@ -11339,8 +11542,11 @@ Operand *AArch64CGFunc::SelectCAtomicLoadN(IntrinsicopNode &intrinsicopNode) auto *addrOpnd = HandleExpr(intrinsicopNode, *intrinsicopNode.Opnd(0)); auto *memOrderOpnd = intrinsicopNode.Opnd(1); auto primType = intrinsicopNode.GetPrimType(); - auto *memOrderConst = static_cast(static_cast(memOrderOpnd)->GetConstVal()); - auto memOrder = static_cast(memOrderConst->GetExtValue()); + std::memory_order memOrder = std::memory_order_seq_cst; + if (memOrderOpnd->IsConstval()) { + auto *memOrderConst = static_cast(static_cast(memOrderOpnd)->GetConstVal()); + memOrder = static_cast(memOrderConst->GetExtValue()); + } return SelectAtomicLoad(*addrOpnd, primType, PickMemOrder(memOrder, true)); } @@ -11356,14 +11562,19 @@ Operand *AArch64CGFunc::SelectCAtomicLoadN(IntrinsicopNode &intrinsicopNode) * a load-acquire would replace ldr if acquire needed * a store-relase would replace str if release needed */ -Operand *AArch64CGFunc::SelectCAtomicExchangeN(IntrinsicopNode &intrinsicopNode) +Operand *AArch64CGFunc::SelectCAtomicExchangeN(const IntrinsiccallNode &intrinsiccallNode) { - auto primType = intrinsicopNode.GetPrimType(); - auto *addrOpnd = HandleExpr(intrinsicopNode, *intrinsicopNode.Opnd(0)); - auto *valueOpnd = HandleExpr(intrinsicopNode, *intrinsicopNode.Opnd(1)); - auto *memOrderOpnd = intrinsicopNode.Opnd(kInsnThirdOpnd); - auto *memOrderConst = static_cast(static_cast(memOrderOpnd)->GetConstVal()); - auto memOrder = static_cast(memOrderConst->GetExtValue()); + auto primType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(intrinsiccallNode.GetTyIdx())->GetPrimType(); + auto *addrOpnd = HandleExpr(intrinsiccallNode, *intrinsiccallNode.Opnd(0)); + auto *valueOpnd = HandleExpr(intrinsiccallNode, *intrinsiccallNode.Opnd(1)); + auto *memOrderOpnd = intrinsiccallNode.Opnd(kInsnThirdOpnd); + + /* slect memry order */ + std::memory_order memOrder = std::memory_order_seq_cst; + if (memOrderOpnd->IsConstval()) { + auto *memOrderConst = static_cast(static_cast(memOrderOpnd)->GetConstVal()); + memOrder = static_cast(memOrderConst->GetExtValue()); + } auto *result = SelectAtomicLoad(*addrOpnd, primType, PickMemOrder(memOrder, true)); SelectAtomicStore(*valueOpnd, *addrOpnd, primType, PickMemOrder(memOrder, false)); return result; @@ -11460,6 +11671,13 @@ Operand *AArch64CGFunc::SelectAArch64align(const IntrinsicopNode &intrnNode, boo return resultReg; } +void AArch64CGFunc::SelectCDIVException() +{ + uint32 breakImm = 1000; + ImmOperand &immOpnd = CreateImmOperand(breakImm, maplebe::k16BitSize, false); + GetCurBB()->AppendInsn(GetInsnBuilder()->BuildInsn(MOP_brk, immOpnd)); +} + /* * NOTE: consider moving the following things into aarch64_cg.cpp They may * serve not only inrinsics, but other MapleIR instructions as well. @@ -12238,6 +12456,7 @@ uint32 ValidShiftConst(PrimType rType) RegOperand *AArch64CGFunc::SelectVectorShiftImm(PrimType rType, Operand *o1, Operand *imm, int32 sVal, Opcode opc) { + auto resultType = FilterOneElementVectorType(rType); RegOperand *res = &CreateRegisterOperandOfType(rType); /* result operand */ VectorRegSpec *vecSpecDest = GetMemoryPool()->New(rType); VectorRegSpec *vecSpec1 = GetMemoryPool()->New(rType); /* vector operand 1 */ @@ -12264,11 +12483,7 @@ RegOperand *AArch64CGFunc::SelectVectorShiftImm(PrimType rType, Operand *o1, Ope } if (needDup) { /* Dup constant to vector reg */ - MOperator mOp = GetPrimTypeSize(rType) > k8ByteSize ? MOP_vmovvi : MOP_vmovui; - VectorInsn &vInsn = GetInsnBuilder()->BuildVectorInsn(mOp, AArch64CG::kMd[mOp]); - vInsn.AddOpndChain(*res).AddOpndChain(*imm); - vInsn.PushRegSpecEntry(vecSpecDest); - GetCurBB()->AppendInsn(vInsn); + SelectCopy(*res, resultType, *imm, imm->GetSize() == k64BitSize ? PTY_u64 : PTY_u32); res = SelectVectorShift(rType, o1, rType, res, rType, opc); return res; } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_ebo.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_ebo.cpp index 1c857787ad274b36762b6444183494b1dbf4fcf2..fe4066a6390e9b79f94cfd8f40ca1f897f23d803 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_ebo.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_ebo.cpp @@ -498,6 +498,7 @@ bool AArch64Ebo::DoConstProp(Insn &insn, uint32 idx, Operand &opnd) case MOP_xmovrr: case MOP_wmovrr: { DEBUG_ASSERT(idx == kInsnSecondOpnd, "src const for move must be the second operand."); + MOperator mOp = (mopCode == MOP_wmovrr) ? MOP_wmovri32 : MOP_xmovri64; uint32 targetSize = insn.GetOperand(idx).GetSize(); if (src->GetSize() != targetSize) { src = static_cast(src->Clone(*cgFunc->GetMemoryPool())); @@ -509,9 +510,15 @@ bool AArch64Ebo::DoConstProp(Insn &insn, uint32 idx, Operand &opnd) LogInfo::MapleLogger() << " Do constprop:Prop constval " << src->GetValue() << "into insn:\n"; insn.Dump(); } - insn.SetOperand(kInsnSecondOpnd, *src); - MOperator mOp = (mopCode == MOP_wmovrr) ? MOP_wmovri32 : MOP_xmovri64; insn.SetMOP(AArch64CG::kMd[mOp]); + src = static_cast(src->Clone(*cgFunc->GetMemoryPool())); + CHECK_FATAL(src != nullptr, "pointer result is null"); + src->SetSize(insn.GetOperand(idx).GetSize()); + if (insn.GetOperandSize(kInsnSecondOpnd) == k32BitSize) { + uint64 newVal = static_cast(src->GetValue()) & UINT32_MAX; + src->SetValue(static_cast(newVal)); + } + insn.SetOperand(kInsnSecondOpnd, *src); if (EBO_DUMP) { LogInfo::MapleLogger() << " after constprop the insn is:\n"; insn.Dump(); @@ -819,6 +826,9 @@ bool AArch64Ebo::SimplifyBothConst(BB &bb, Insn &insn, const ImmOperand &immOper } else { MOperator newmOp = opndSize == k64BitSize ? MOP_xmovri64 : MOP_wmovri32; Insn &newInsn = cgFunc->GetInsnBuilder()->BuildInsn(newmOp, *res, *immOperand); + if (!VERIFY_INSN(&newInsn)) { // insn needs to be split, so we do not implement the opt. + return false; + } bb.ReplaceInsn(insn, newInsn); } return true; diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_global.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_global.cpp index d39068b0f098437ceb0bb4a9de5d6af72ed9b073..96e93665c8e28c82993b47d999a52ccb22fba789 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_global.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_global.cpp @@ -453,7 +453,8 @@ void ForwardPropPattern::Run() { bool secondTime = false; do { - FOR_ALL_BB(bb, &cgFunc) { + FOR_ALL_BB(bb, &cgFunc) + { if (bb->IsUnreachable() || (secondTime && modifiedBB.find(bb) == modifiedBB.end())) { continue; } @@ -462,7 +463,8 @@ void ForwardPropPattern::Run() modifiedBB.erase(bb); } - FOR_BB_INSNS(insn, bb) { + FOR_BB_INSNS(insn, bb) + { Init(); if (!CheckCondition(*insn)) { if (insn->GetMachineOpcode() == MOP_xmovrr_uxtw) { @@ -842,7 +844,8 @@ void BackPropPattern::Run() bool secondTime = false; std::set modifiedBB; do { - FOR_ALL_BB(bb, &cgFunc) { + FOR_ALL_BB(bb, &cgFunc) + { if (bb->IsUnreachable() || (secondTime && modifiedBB.find(bb) == modifiedBB.end())) { continue; } @@ -851,7 +854,8 @@ void BackPropPattern::Run() modifiedBB.erase(bb); } - FOR_BB_INSNS_REV(insn, bb) { + FOR_BB_INSNS_REV(insn, bb) + { Init(); if (!CheckCondition(*insn)) { continue; @@ -940,8 +944,10 @@ void CmpCsetPattern::Init() void CmpCsetPattern::Run() { - FOR_ALL_BB(bb, &cgFunc) { - FOR_BB_INSNS(insn, bb) { + FOR_ALL_BB(bb, &cgFunc) + { + FOR_BB_INSNS(insn, bb) + { Init(); if (!CheckCondition(*insn)) { continue; @@ -989,8 +995,10 @@ void CselPattern::Optimize(Insn &insn) void CselPattern::Run() { - FOR_ALL_BB(bb, &cgFunc) { - FOR_BB_INSNS_SAFE(insn, bb, nextInsn) { + FOR_ALL_BB(bb, &cgFunc) + { + FOR_BB_INSNS_SAFE(insn, bb, nextInsn) + { if (!CheckCondition(*insn)) { continue; } @@ -1137,11 +1145,13 @@ void RedundantUxtPattern::Init() void RedundantUxtPattern::Run() { - FOR_ALL_BB(bb, &cgFunc) { + FOR_ALL_BB(bb, &cgFunc) + { if (bb->IsUnreachable()) { continue; } - FOR_BB_INSNS_SAFE(insn, bb, nextInsn) { + FOR_BB_INSNS_SAFE(insn, bb, nextInsn) + { Init(); if (!CheckCondition(*insn)) { continue; @@ -1294,11 +1304,13 @@ void LocalVarSaveInsnPattern::Init() void LocalVarSaveInsnPattern::Run() { - FOR_ALL_BB(bb, &cgFunc) { + FOR_ALL_BB(bb, &cgFunc) + { if (bb->IsCleanup()) { continue; } - FOR_BB_INSNS(insn, bb) { + FOR_BB_INSNS(insn, bb) + { if (!insn->IsMachineInstruction()) { continue; } @@ -1765,8 +1777,10 @@ void ExtendShiftOptPattern::Run() if (!cgFunc.GetMirModule().IsCModule()) { return; } - FOR_ALL_BB_REV(bb, &cgFunc) { - FOR_BB_INSNS_REV(insn, bb) { + FOR_ALL_BB_REV(bb, &cgFunc) + { + FOR_BB_INSNS_REV(insn, bb) + { if (!insn->IsMachineInstruction()) { continue; } @@ -1780,8 +1794,10 @@ void ExtenToMovPattern::Run() if (!cgFunc.GetMirModule().IsCModule()) { return; } - FOR_ALL_BB(bb, &cgFunc) { - FOR_BB_INSNS(insn, bb) { + FOR_ALL_BB(bb, &cgFunc) + { + FOR_BB_INSNS(insn, bb) + { if (!insn->IsMachineInstruction()) { continue; } @@ -1948,8 +1964,10 @@ void ExtenToMovPattern::Optimize(Insn &insn) void SameDefPattern::Run() { - FOR_ALL_BB_REV(bb, &cgFunc) { - FOR_BB_INSNS_REV(insn, bb) { + FOR_ALL_BB_REV(bb, &cgFunc) + { + FOR_BB_INSNS_REV(insn, bb) + { if (!CheckCondition(*insn) || !bb->GetEhPreds().empty()) { continue; } @@ -2060,7 +2078,8 @@ bool SameDefPattern::SrcRegIsRedefined(regno_t regNo) { AArch64ReachingDefinition *a64RD = static_cast(cgFunc.GetRD()); if (currInsn->GetBB() == sameInsn->GetBB()) { - FOR_BB_INSNS(insn, currInsn->GetBB()) { + FOR_BB_INSNS(insn, currInsn->GetBB()) + { if (insn->GetMachineOpcode() == MOP_xbl) { return true; } @@ -2160,6 +2179,9 @@ void AndCbzPattern::Optimize(Insn &insn) auto &label = static_cast(insn.GetOperand(kInsnSecondOpnd)); ImmOperand &tbzImm = aarchFunc.CreateImmOperand(tbzVal, k8BitSize, false); Insn &newInsn = cgFunc.GetInsnBuilder()->BuildInsn(newMop, prevInsn->GetOperand(kInsnSecondOpnd), tbzImm, label); + if (!VERIFY_INSN(&newInsn)) { + return; + } newInsn.SetId(insn.GetId()); bb->ReplaceInsn(insn, newInsn); if (GLOBAL_DUMP) { @@ -2176,8 +2198,10 @@ void AndCbzPattern::Optimize(Insn &insn) void AndCbzPattern::Run() { Init(); - FOR_ALL_BB_REV(bb, &cgFunc) { - FOR_BB_INSNS_REV(insn, bb) { + FOR_ALL_BB_REV(bb, &cgFunc) + { + FOR_BB_INSNS_REV(insn, bb) + { if (!insn->IsMachineInstruction() || !CheckCondition(*insn)) { continue; } @@ -2324,8 +2348,10 @@ void SameRHSPropPattern::Optimize(Insn &insn) void SameRHSPropPattern::Run() { Init(); - FOR_ALL_BB_REV(bb, &cgFunc) { - FOR_BB_INSNS_REV(insn, bb) { + FOR_ALL_BB_REV(bb, &cgFunc) + { + FOR_BB_INSNS_REV(insn, bb) + { if (!CheckCondition(*insn)) { continue; } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_imm_valid.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_imm_valid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f41a5d0cc6b914feee536bdee2bbb4e0445ed3da --- /dev/null +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_imm_valid.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "aarch64_imm_valid.h" +#include +#include +#include + +namespace maplebe { +const std::set ValidBitmaskImmSet = { +#include "valid_bitmask_imm.txt" +}; +constexpr uint32 kMaxBitTableSize = 5; +constexpr std::array kBitmaskImmMultTable = { + 0x0000000100000001UL, 0x0001000100010001UL, 0x0101010101010101UL, 0x1111111111111111UL, 0x5555555555555555UL, +}; +namespace aarch64 { +bool IsBitmaskImmediate(uint64 val, uint32 bitLen) +{ + DEBUG_ASSERT(val != 0, "IsBitmaskImmediate() don's accept 0 or -1"); + DEBUG_ASSERT(static_cast(val) != -1, "IsBitmaskImmediate() don's accept 0 or -1"); + if ((bitLen == k32BitSize) && (static_cast(val) == -1)) { + return false; + } + uint64 val2 = val; + if (bitLen == k32BitSize) { + val2 = (val2 << k32BitSize) | (val2 & ((1ULL << k32BitSize) - 1)); + } + bool expectedOutcome = (ValidBitmaskImmSet.find(val2) != ValidBitmaskImmSet.end()); + + if ((val & 0x1) != 0) { + /* + * we want to work with + * 0000000000000000000000000000000000000000000001100000000000000000 + * instead of + * 1111111111111111111111111111111111111111111110011111111111111111 + */ + val = ~val; + } + + if (bitLen == k32BitSize) { + val = (val << k32BitSize) | (val & ((1ULL << k32BitSize) - 1)); + } + + /* get the least significant bit set and add it to 'val' */ + uint64 tmpVal = val + (val & static_cast(UINT64_MAX - val + 1)); + + /* now check if tmp is a power of 2 or tmpVal==0. */ + tmpVal = tmpVal & (tmpVal - 1); + if (tmpVal == 0) { + if (!expectedOutcome) { +#if defined(DEBUG) && DEBUG + LogInfo::MapleLogger() << "0x" << std::hex << std::setw(static_cast(k16ByteSize)) << std::setfill('0') + << static_cast(val) << "\n"; +#endif + return false; + } + DEBUG_ASSERT(expectedOutcome, "incorrect implementation: not valid value but returning true"); + /* power of two or zero ; return true */ + return true; + } + + int32 p0 = __builtin_ctzll(val); + int32 p1 = __builtin_ctzll(tmpVal); + int64 diff = p1 - p0; + + /* check if diff is a power of two; return false if not. */ + if ((static_cast(diff) & (static_cast(diff) - 1)) != 0) { + DEBUG_ASSERT(!expectedOutcome, "incorrect implementation: valid value but returning false"); + return false; + } + + uint32 logDiff = static_cast(__builtin_ctzll(static_cast(diff))); + uint64 pattern = val & ((1ULL << static_cast(diff)) - 1); +#if defined(DEBUG) && DEBUG + bool ret = (val == pattern * kBitmaskImmMultTable[kMaxBitTableSize - logDiff]); + DEBUG_ASSERT(expectedOutcome == ret, "incorrect implementation: return value does not match expected outcome"); + return ret; +#else + return val == pattern * kBitmaskImmMultTable[kMaxBitTableSize - logDiff]; +#endif +} +} // namespace aarch64 +} // namespace maplebe diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_isa.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_isa.cpp index f439ec5a3abb2a428853faaccfb626574207bbf2..79fe3017d1326d4abc27d075770e92b8abe588c6 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_isa.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_isa.cpp @@ -161,5 +161,80 @@ int64 GetMemOpndOffsetValue(Operand *o) int64 offsetValue = ofStOpnd ? ofStOpnd->GetOffsetValue() : 0LL; return offsetValue; } + +bool IsSub(const Insn &insn) +{ + MOperator curMop = insn.GetMachineOpcode(); + switch (curMop) { + case MOP_xsubrrr: + case MOP_xsubrrrs: + case MOP_xsubrri24: + case MOP_xsubrri12: + case MOP_wsubrrr: + case MOP_wsubrrrs: + case MOP_wsubrri24: + case MOP_wsubrri12: + return true; + default: + return false; + } +} + +MOperator GetMopSub2Subs(const Insn &insn) +{ + MOperator curMop = insn.GetMachineOpcode(); + switch (curMop) { + case MOP_xsubrrr: + return MOP_xsubsrrr; + case MOP_xsubrrrs: + return MOP_xsubsrrrs; + case MOP_xsubrri24: + return MOP_xsubsrri24; + case MOP_xsubrri12: + return MOP_xsubsrri12; + case MOP_wsubrrr: + return MOP_wsubsrrr; + case MOP_wsubrrrs: + return MOP_wsubsrrrs; + case MOP_wsubrri24: + return MOP_wsubsrri24; + case MOP_wsubrri12: + return MOP_wsubsrri12; + default: + return curMop; + } +} + +// Returns the number of trailing 0-bits in x, starting at the least significant bit position. +// If x is 0, the result is -1. +int32 GetTail0BitNum(int64 val) +{ + uint32 bitNum = 0; + for (; bitNum < k64BitSize; bitNum++) { + if (((1ULL << bitNum) & static_cast(val)) != 0) { + break; + } + } + if (bitNum == k64BitSize) { + return -1; + } + return static_cast(bitNum); +} + +// Returns the number of leading 0-bits in x, starting at the most significant bit position. +// If x is 0, the result is -1. +int32 GetHead0BitNum(int64 val) +{ + uint32 bitNum = 0; + for (; bitNum < k64BitSize; bitNum++) { + if (((0x8000000000000000ULL >> bitNum) & static_cast(val)) != 0) { + break; + } + } + if (bitNum == k64BitSize) { + return -1; + } + return static_cast(bitNum); +} } /* namespace AArch64isa */ } /* namespace maplebe */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_memlayout.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_memlayout.cpp index 294a64a2c6e4836bd947a8190de102f531b46ec1..698f0356765b7367d2dd5034dfd9936d7e7f826e 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_memlayout.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_memlayout.cpp @@ -289,7 +289,7 @@ void AArch64MemLayout::LayoutFormalParams() } } if (cgFunc->GetCG()->GetCGOptions().WithDwarf() && ploc.reg0 == kRinvalid) { - cgFunc->AddDIESymbolLocation(sym, symLoc); + cgFunc->AddDIESymbolLocation(sym, symLoc, true); } } } @@ -345,7 +345,7 @@ void AArch64MemLayout::LayoutLocalVariables(std::vector &tempVar, s segLocals.SetSize(segLocals.GetSize() + be.GetTypeSize(tyIdx)); } if (cgFunc->GetCG()->GetCGOptions().WithDwarf()) { - cgFunc->AddDIESymbolLocation(sym, symLoc); + cgFunc->AddDIESymbolLocation(sym, symLoc, false); } } } @@ -556,6 +556,25 @@ uint32 AArch64MemLayout::RealStackFrameSize() const return static_cast(size); } +// from cold area to bottom of stk +// [cold,16] + [GR, 16] + [VR, 16] + stack protect (if has) +uint64 AArch64MemLayout::GetSizeOfColdToStk() const +{ + uint64 total = 0; + auto coldsize = RoundUp(GetSizeOfSegCold(), k16BitSize); + total += coldsize; + if (GetSizeOfGRSaveArea() > 0) { + total += RoundUp(GetSizeOfGRSaveArea(), kAarch64StackPtrAlignment); + } + if (GetSizeOfVRSaveArea() > 0) { + total += RoundUp(GetSizeOfVRSaveArea(), kAarch64StackPtrAlignment); + } + if (cgFunc->GetCG()->IsStackProtectorStrong() || cgFunc->GetCG()->IsStackProtectorAll()) { + total += static_cast(kAarch64StackPtrAlignment); + } + return total; +} + int32 AArch64MemLayout::GetRefLocBaseLoc() const { AArch64CGFunc *aarchCGFunc = static_cast(cgFunc); @@ -581,4 +600,32 @@ int32 AArch64MemLayout::GetVRSaveAreaBaseLoc() total -= static_cast(SizeOfArgsToStackPass()) + cgFunc->GetFunction().GetFrameReseverdSlot(); return total; } + +// fp - callee base = +// RealStackFrameSize - [GR,16] - [VR,16] - [cold,16] - ([callee] - 16(fplr)) - stack protect - stkpass +// callsave area size includes fp lr, real callee save area size is callee save size - fplr +// fp lr located on top of args pass area. +int32 AArch64MemLayout::GetCalleeSaveBaseLoc() const +{ + uint32 offset = RealStackFrameSize() - static_cast(cgFunc)->SizeOfCalleeSaved(); + offset = (offset - SizeOfArgsToStackPass()) + kSizeOfFplr - cgFunc->GetFunction().GetFrameReseverdSlot(); + + if (cgFunc->GetMirModule().IsCModule() && cgFunc->GetFunction().GetAttr(FUNCATTR_varargs)) { + /* GR/VR save areas are above the callee save area */ + // According to AAPCS64 document: + // __gr_top: set to the address of the byte immediately following the general register argument save area, the + // end of the save area being aligned to a 16 byte boundary. + // __vr_top: set to the address of the byte immediately following the FP/SIMD register argument save area, the + // end of the save area being aligned to a 16 byte boundary. + auto saveareasize = RoundUp(GetSizeOfGRSaveArea(), kAarch64StackPtrAlignment) + + RoundUp(GetSizeOfVRSaveArea(), kAarch64StackPtrAlignment); + offset = static_cast(offset - saveareasize); + } + offset -= static_cast(RoundUp(GetSizeOfSegCold(), k16BitSize)); + + if (cgFunc->GetCG()->IsStackProtectorStrong() || cgFunc->GetCG()->IsStackProtectorAll()) { + offset -= static_cast(kAarch64StackPtrAlignment); + } + return static_cast(offset); +} } /* namespace maplebe */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_offset_adjust.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_offset_adjust.cpp index 1dab11706ebbd2ed1321a61f5204f0e8d70c3403..59f391ffddaa295ee9cb76fc9402f59c2406b54d 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_offset_adjust.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_offset_adjust.cpp @@ -21,8 +21,10 @@ namespace maplebe { void AArch64FPLROffsetAdjustment::Run() { AArch64CGFunc *aarchCGFunc = static_cast(cgFunc); - FOR_ALL_BB(bb, aarchCGFunc) { - FOR_BB_INSNS_SAFE(insn, bb, ninsn) { // AdjustmentOffsetForOpnd may replace curInsn + FOR_ALL_BB(bb, aarchCGFunc) + { + FOR_BB_INSNS_SAFE(insn, bb, ninsn) + { // AdjustmentOffsetForOpnd may replace curInsn if (!insn->IsMachineInstruction()) { continue; } @@ -51,19 +53,21 @@ void AArch64FPLROffsetAdjustment::Run() void AArch64FPLROffsetAdjustment::AdjustmentOffsetForOpnd(Insn &insn) const { + bool isLmbc = (aarchCGFunc->GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc); + AArch64reg stackBaseReg = isLmbc ? R29 : (aarchCGFunc->UseFP() ? R29 : RSP); uint32 opndNum = insn.GetOperandSize(); bool replaceFP = false; for (uint32 i = 0; i < opndNum; ++i) { Operand &opnd = insn.GetOperand(i); if (opnd.IsRegister()) { - auto ®Opnd = static_cast(opnd); + auto ®Opnd = static_cast(opnd); if (regOpnd.IsOfVary()) { insn.SetOperand(i, aarchCGFunc->GetOrCreateStackBaseRegOperand()); regOpnd = aarchCGFunc->GetOrCreateStackBaseRegOperand(); } if (regOpnd.GetRegisterNumber() == RFP) { insn.SetOperand(i, - aarchCGFunc->GetOrCreatePhysicalRegisterOperand(stackBaseReg, k64BitSize, kRegTyInt)); + aarchCGFunc->GetOrCreatePhysicalRegisterOperand(stackBaseReg, k64BitSize, kRegTyInt)); replaceFP = true; } } else if (opnd.IsMemoryAccessOperand()) { @@ -76,67 +80,20 @@ void AArch64FPLROffsetAdjustment::AdjustmentOffsetForOpnd(Insn &insn) const if (replaceFP && !aarchCGFunc->UseFP()) { AdjustmentStackPointer(insn); } - if (insn.IsLoad() || insn.IsStore()) { - for (uint32 i = 0; i < opndNum; ++i) { - Operand &opnd = insn.GetOperand(i); - if (opnd.IsMemoryAccessOperand()) { - auto &memOpnd = static_cast(opnd); - if ((memOpnd.GetAddrMode() != MemOperand::kAddrModeBOi) || !memOpnd.IsIntactIndexed()) { - continue; - } - if (!aarchCGFunc->IsOperandImmValid(insn.GetMachineOpcode(), &memOpnd, i)) { - MemOperand &newMemOpnd = aarchCGFunc->SplitOffsetWithAddInstruction( - memOpnd, memOpnd.GetSize(), static_cast(R16), false, &insn); - insn.SetOperand(i, newMemOpnd); - } - } - } - } else { - for (uint32 i = 0; i < opndNum; ++i) { - Operand &opnd = insn.GetOperand(i); - if (opnd.IsIntImmediate()) { - auto &immOpnd = static_cast(opnd); - if (!aarchCGFunc->IsOperandImmValid(insn.GetMachineOpcode(), &immOpnd, i)) { - if (insn.GetMachineOpcode() >= MOP_xaddrri24 && insn.GetMachineOpcode() <= MOP_waddrri12) { - PrimType destTy = - static_cast(insn.GetOperand(kInsnFirstOpnd)).GetSize() == k64BitSize - ? PTY_i64 - : PTY_i32; - RegOperand *resOpnd = &static_cast(insn.GetOperand(kInsnFirstOpnd)); - ImmOperand ©ImmOpnd = aarchCGFunc->CreateImmOperand(immOpnd.GetValue(), immOpnd.GetSize(), - immOpnd.IsSignedValue()); - aarchCGFunc->SelectAddAfterInsn(*resOpnd, insn.GetOperand(kInsnSecondOpnd), copyImmOpnd, destTy, - false, insn); - insn.GetBB()->RemoveInsn(insn); - } else if (insn.GetMachineOpcode() == MOP_xsubrri12 || insn.GetMachineOpcode() == MOP_wsubrri12) { - if (immOpnd.IsSingleInstructionMovable()) { - RegOperand &tempReg = - aarchCGFunc->GetOrCreatePhysicalRegisterOperand(R16, k64BitSize, kRegTyInt); - bool is64bit = insn.GetOperand(kInsnFirstOpnd).GetSize() == k64BitSize; - MOperator tempMovOp = is64bit ? MOP_xmovri64 : MOP_wmovri32; - Insn &tempMov = cgFunc->GetInsnBuilder()->BuildInsn(tempMovOp, tempReg, immOpnd); - insn.SetOperand(i, tempReg); - insn.SetMOP(is64bit ? AArch64CG::kMd[MOP_xsubrrr] : AArch64CG::kMd[MOP_wsubrrr]); - (void)insn.GetBB()->InsertInsnBefore(insn, tempMov); - } - } else { - CHECK_FATAL(false, "NIY"); - } - } - } - } + if (!VERIFY_INSN(&insn)) { // split insn + SPLIT_INSN(&insn, aarchCGFunc); } } void AArch64FPLROffsetAdjustment::AdjustMemBaseReg(Insn &insn, uint32 i, bool &replaceFP) const { Operand &opnd = insn.GetOperand(i); - auto &currMemOpnd = static_cast(opnd); + auto &currMemOpnd = static_cast(opnd); MemOperand *newMemOpnd = currMemOpnd.Clone(*aarchCGFunc->GetMemoryPool()); CHECK_NULL_FATAL(newMemOpnd); if (newMemOpnd->GetBaseRegister() != nullptr) { if (newMemOpnd->GetBaseRegister()->IsOfVary()) { - newMemOpnd->SetBaseRegister(static_cast(aarchCGFunc->GetOrCreateStackBaseRegOperand())); + newMemOpnd->SetBaseRegister(static_cast(aarchCGFunc->GetOrCreateStackBaseRegOperand())); } RegOperand *memBaseReg = newMemOpnd->GetBaseRegister(); if (memBaseReg->GetRegisterNumber() == RFP) { @@ -146,9 +103,8 @@ void AArch64FPLROffsetAdjustment::AdjustMemBaseReg(Insn &insn, uint32 i, bool &r replaceFP = true; } } - if (newMemOpnd->GetBaseRegister() != nullptr && - (newMemOpnd->GetBaseRegister()->GetRegisterNumber() == RFP || - newMemOpnd->GetBaseRegister()->GetRegisterNumber() == RSP)) { + if (newMemOpnd->GetBaseRegister() != nullptr && (newMemOpnd->GetBaseRegister()->GetRegisterNumber() == RFP || + newMemOpnd->GetBaseRegister()->GetRegisterNumber() == RSP)) { newMemOpnd->SetStackMem(true); } insn.SetOperand(i, *newMemOpnd); @@ -160,7 +116,7 @@ void AArch64FPLROffsetAdjustment::AdjustMemOfstVary(Insn &insn, uint32 i) const // in subsequent steps, which will cause some unknown errors. So, we're going to do a unified // split after all the steps are complete. Operand &opnd = insn.GetOperand(i); - auto &currMemOpnd = static_cast(opnd); + auto &currMemOpnd = static_cast(opnd); if (currMemOpnd.GetAddrMode() != MemOperand::kAddrModeBOi) { return; } @@ -168,9 +124,10 @@ void AArch64FPLROffsetAdjustment::AdjustMemOfstVary(Insn &insn, uint32 i) const CHECK_NULL_FATAL(ofstOpnd); if (ofstOpnd->GetVary() == kUnAdjustVary) { MemLayout *memLayout = aarchCGFunc->GetMemlayout(); - ofstOpnd->AdjustOffset(static_cast( - static_cast(memLayout)->RealStackFrameSize() - - memLayout->SizeOfArgsToStackPass() - cgFunc->GetFunction().GetFrameReseverdSlot())); + ofstOpnd->AdjustOffset(static_cast(static_cast(memLayout)->RealStackFrameSize() - + memLayout->SizeOfArgsToStackPass() - + static_cast(memLayout)->GetSizeOfColdToStk() - + cgFunc->GetFunction().GetFrameReseverdSlot())); ofstOpnd->SetVary(kAdjustVary); } } @@ -180,11 +137,13 @@ void AArch64FPLROffsetAdjustment::AdjustmentOffsetForImmOpnd(Insn &insn, uint32 // Note: SplitInsn invalidates the current insn. However, the current insn will still be manipulated // in subsequent steps, which will cause some unknown errors. So, we're going to do a unified // split after all the steps are complete. - auto &immOpnd = static_cast(insn.GetOperand(index)); - auto *memLayout = static_cast(aarchCGFunc->GetMemlayout()); + auto &immOpnd = static_cast(insn.GetOperand(index)); + auto *memLayout = static_cast(aarchCGFunc->GetMemlayout()); if (immOpnd.GetVary() == kUnAdjustVary) { - int64 ofst = static_cast(memLayout)->RealStackFrameSize() - - memLayout->SizeOfArgsToStackPass() - cgFunc->GetFunction().GetFrameReseverdSlot(); + int64 ofst = static_cast( + memLayout->RealStackFrameSize() - + static_cast(memLayout->SizeOfArgsToStackPass() + memLayout->GetSizeOfColdToStk()) - + cgFunc->GetFunction().GetFrameReseverdSlot()); if (insn.GetMachineOpcode() == MOP_xsubrri12 || insn.GetMachineOpcode() == MOP_wsubrri12) { immOpnd.SetValue(immOpnd.GetValue() - ofst); if (immOpnd.GetValue() < 0) { @@ -203,33 +162,37 @@ void AArch64FPLROffsetAdjustment::AdjustmentStackPointer(Insn &insn) const // Note: SplitInsn invalidates the current insn. However, the current insn will still be manipulated // in subsequent steps, which will cause some unknown errors. So, we're going to do a unified // split after all the steps are complete. - auto *aarch64memlayout = static_cast(aarchCGFunc->GetMemlayout()); - uint32 offset = - static_cast(aarch64memlayout->SizeOfArgsToStackPass() + cgFunc->GetFunction().GetFrameReseverdSlot()); + auto *aarch64memlayout = static_cast(aarchCGFunc->GetMemlayout()); + uint32 offset = aarch64memlayout->SizeOfArgsToStackPass() + cgFunc->GetFunction().GetFrameReseverdSlot(); if (offset == 0) { return; } if (insn.IsLoad() || insn.IsStore()) { - auto *memOpnd = static_cast(insn.GetMemOpnd()); + auto *memOpnd = static_cast(insn.GetMemOpnd()); CHECK_NULL_FATAL(memOpnd); + DEBUG_ASSERT(memOpnd->GetBaseRegister() != nullptr, "Unexpect, need check"); CHECK_FATAL(memOpnd->IsIntactIndexed(), "unsupport yet"); ImmOperand *ofstOpnd = memOpnd->GetOffsetOperand(); CHECK_NULL_FATAL(ofstOpnd); - ImmOperand *newOfstOpnd = &aarchCGFunc->GetOrCreateOfstOpnd( - static_cast(ofstOpnd->GetValue() + offset), ofstOpnd->GetSize()); + ImmOperand *newOfstOpnd = + &aarchCGFunc->GetOrCreateOfstOpnd(static_cast(ofstOpnd->GetValue() + offset), ofstOpnd->GetSize()); memOpnd->SetOffsetOperand(*newOfstOpnd); } else { switch (insn.GetMachineOpcode()) { case MOP_waddrri12: case MOP_xaddrri12: { - auto *newAddImmOpnd = static_cast( - static_cast(insn.GetOperand(kInsnThirdOpnd)).Clone(*cgFunc->GetMemoryPool())); + DEBUG_ASSERT(static_cast(insn.GetOperand(kInsnSecondOpnd)).GetRegisterNumber() == RSP, + "regNumber should be changed in AdjustmentOffsetForOpnd"); + auto *newAddImmOpnd = static_cast( + static_cast(insn.GetOperand(kInsnThirdOpnd)).Clone(*cgFunc->GetMemoryPool())); newAddImmOpnd->SetValue(newAddImmOpnd->GetValue() + offset); insn.SetOperand(kInsnThirdOpnd, *newAddImmOpnd); break; } case MOP_waddrri24: case MOP_xaddrri24: { + DEBUG_ASSERT(static_cast(insn.GetOperand(kInsnSecondOpnd)).GetRegisterNumber() == RSP, + "regNumber should be changed in AdjustmentOffsetForOpnd"); RegOperand &tempReg = aarchCGFunc->GetOrCreatePhysicalRegisterOperand(R16, k64BitSize, kRegTyInt); ImmOperand &offsetReg = aarchCGFunc->CreateImmOperand(offset, k64BitSize, false); aarchCGFunc->SelectAddAfterInsn(tempReg, insn.GetOperand(kInsnSecondOpnd), offsetReg, PTY_i64, false, @@ -239,8 +202,8 @@ void AArch64FPLROffsetAdjustment::AdjustmentStackPointer(Insn &insn) const } case MOP_wsubrri12: case MOP_xsubrri12: { - auto *newAddImmOpnd = static_cast( - static_cast(insn.GetOperand(kInsnThirdOpnd)).Clone(*cgFunc->GetMemoryPool())); + auto *newAddImmOpnd = static_cast( + static_cast(insn.GetOperand(kInsnThirdOpnd)).Clone(*cgFunc->GetMemoryPool())); newAddImmOpnd->SetValue(newAddImmOpnd->GetValue() - offset); if (newAddImmOpnd->GetValue() < 0) { newAddImmOpnd->Negate(); @@ -249,6 +212,14 @@ void AArch64FPLROffsetAdjustment::AdjustmentStackPointer(Insn &insn) const insn.SetOperand(kInsnThirdOpnd, *newAddImmOpnd); break; } + case MOP_waddsrri12: + case MOP_xaddsrri12: { + auto *newAddImmOpnd = static_cast( + static_cast(insn.GetOperand(kInsnFourthOpnd)).Clone(*cgFunc->GetMemoryPool())); + newAddImmOpnd->SetValue(newAddImmOpnd->GetValue() + offset); + insn.SetOperand(kInsnFourthOpnd, *newAddImmOpnd); + break; + } default: { // Only some special insn will replace FP, insn.Dump(); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_peep.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_peep.cpp index 0dfb9da295ba89e947e389c88e950981038767ce..ebeb7f870b16e13d1ecfc56de3147a0727e5e756 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_peep.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_peep.cpp @@ -1308,6 +1308,9 @@ void AndCmpBranchesToTbzPattern::Run(BB &bb, Insn &insn) ImmOperand &tbzImmOpnd = aarFunc->CreateImmOperand(tbzImmVal, k8BitSize, false); Insn &newInsn = cgFunc->GetInsnBuilder()->BuildInsn(newMop, prevAndInsn->GetOperand(kInsnSecondOpnd), tbzImmOpnd, labelOpnd); + if (!VERIFY_INSN(&newInsn)) { + return; + } bb.ReplaceInsn(insn, newInsn); /* update ssa info */ ssaInfo->ReplaceInsn(insn, newInsn); @@ -1559,6 +1562,9 @@ void ZeroCmpBranchesToTbzPattern::Run(BB &bb, Insn &insn) auto &labelOpnd = static_cast(insn.GetOperand(kInsnSecondOpnd)); Insn &newInsn = cgFunc->GetInsnBuilder()->BuildInsn(newMop, *static_cast(regOpnd), bitOpnd, labelOpnd); + if (!VERIFY_INSN(&newInsn)) { + return; + } bb.ReplaceInsn(insn, newInsn); /* update ssa info */ ssaInfo->ReplaceInsn(insn, newInsn); @@ -2792,6 +2798,9 @@ void OneHoleBranchPattern::Run(BB &bb, Insn &insn) ImmOperand &oneHoleOpnd = aarch64CGFunc->CreateImmOperand(0, k8BitSize, false); auto ®Operand = static_cast(prePrevInsn->GetOperand(kInsnSecondOpnd)); Insn &newTbzInsn = cgFunc->GetInsnBuilder()->BuildInsn(newOp, regOperand, oneHoleOpnd, label); + if (!VERIFY_INSN(&newTbzInsn)) { + return; + } bb.ReplaceInsn(insn, newTbzInsn); ssaInfo->ReplaceInsn(insn, newTbzInsn); optSuccess = true; @@ -2927,6 +2936,7 @@ void AArch64CGPeepHole::DoNormalOptimize(BB &bb, Insn &insn) case MOP_wstrb: case MOP_wldrb: { // only strb ldrb can do this pattern, other patterns still need to be done, so there is no break here. + break; } case MOP_wstrh: case MOP_wldrh: @@ -7906,6 +7916,9 @@ void NormRevTbzToTbzPattern::Run(BB &bb, Insn &insn) MOperator useMop = tbzInsn->GetMachineOpcode(); Insn &newInsn = cgFunc->GetInsnBuilder()->BuildInsn(useMop, insn.GetOperand(kInsnSecondOpnd), newImmOpnd, tbzInsn->GetOperand(kInsnThirdOpnd)); + if (!VERIFY_INSN(&newInsn)) { + return; + } bb.ReplaceInsn(*tbzInsn, newInsn); optSuccess = true; /* dump pattern info */ @@ -8021,12 +8034,16 @@ void AddSubMergeLdStPattern::Run(BB &bb, Insn &insn) newInsn = &static_cast(cgFunc)->GetInsnBuilder()->BuildInsn( insnToBeReplaced->GetMachineOpcode(), insnToBeReplaced->GetOperand(kInsnFirstOpnd), *newMemOpnd); } - // Both [RSP, #imm]! and [RSP], #imm should be set true for stackdef. - if (insnUseReg->GetRegisterNumber() == RSP) { - newInsn->SetStackDef(true); + if (!VERIFY_INSN(newInsn)) { + return; + } else { + // Both [RSP, #imm]! and [RSP], #imm should be set true for stackdef. + if (insnUseReg->GetRegisterNumber() == RSP) { + newInsn->SetStackDef(true); + } + bb.ReplaceInsn(*insnToBeReplaced, *newInsn); + bb.RemoveInsn(insn); } - bb.ReplaceInsn(*insnToBeReplaced, *newInsn); - bb.RemoveInsn(insn); } void UbfxAndMergetPattern::Run(BB &bb, Insn &insn) @@ -8138,6 +8155,9 @@ void UbfxAndCbzToTbzPattern::Run(BB &bb, Insn &insn) return; } Insn *newInsn = &cgFunc->GetInsnBuilder()->BuildInsn(newMop, opnd2, imm3, label); + if (!VERIFY_INSN(newInsn)) { + return; + } BB *useInsnBB = useInsn->GetBB(); useInsnBB->ReplaceInsn(*useInsn, *newInsn); if (ssaInfo) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_prop.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_prop.cpp index 8bd880a8e15504baa36f787be3d5fafd24ef0736..80e7824561f4728e64087aa4ec4f93035c8646d1 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_prop.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_prop.cpp @@ -307,6 +307,11 @@ bool A64ConstProp::ArithmeticConstReplace(DUInsnInfo &useDUInfo, ImmOperand &con uint32 useOpndIdx = useOpndInfoIt->first; CHECK_FATAL(useOpndIdx == kInsnSecondOpnd || useOpndIdx == kInsnThirdOpnd, "check this insn"); Insn *newInsn = nullptr; + auto &tempImm = static_cast(*constOpnd.Clone(*constPropMp)); + if (tempImm.GetSize() == k64BitSize && useInsn->GetOperandSize(useOpndIdx) == k32BitSize) { + uint64 newVal = static_cast(tempImm.GetValue()) & UINT32_MAX; + tempImm.SetValue(static_cast(newVal)); + } if (static_cast(cgFunc)->IsOperandImmValid(newMop, &constOpnd, kInsnThirdOpnd)) { if (useOpndIdx == kInsnThirdOpnd) { newInsn = &cgFunc->GetInsnBuilder()->BuildInsn(newMop, useInsn->GetOperand(kInsnFirstOpnd), @@ -887,7 +892,7 @@ RegOperand *A64StrLdrProp::GetReplaceReg(RegOperand &a64Reg) if (a64Reg.IsSSAForm()) { regno_t ssaIndex = a64Reg.GetRegisterNumber(); replaceVersions[ssaIndex] = ssaInfo->FindSSAVersion(ssaIndex); - DEBUG_ASSERT(replaceVersions.size() <= 2, "CHECK THIS CASE IN A64PROP"); // size <= 2 in A64PROP + DEBUG_ASSERT(replaceVersions.size() <= 2, "CHECK THIS CASE IN A64PROP"); // size <= 2 in A64PROP return &a64Reg; } return nullptr; @@ -1431,8 +1436,10 @@ void ExtendShiftPattern::Run() if (!cgFunc.GetMirModule().IsCModule()) { return; } - FOR_ALL_BB_REV(bb, &cgFunc) { - FOR_BB_INSNS_REV(insn, bb) { + FOR_ALL_BB_REV(bb, &cgFunc) + { + FOR_BB_INSNS_REV(insn, bb) + { if (!insn->IsMachineInstruction()) { continue; } @@ -1446,8 +1453,10 @@ void ExtendMovPattern::Run() if (!cgFunc.GetMirModule().IsCModule()) { return; } - FOR_ALL_BB(bb, &cgFunc) { - FOR_BB_INSNS(insn, bb) { + FOR_ALL_BB(bb, &cgFunc) + { + FOR_BB_INSNS(insn, bb) + { if (!insn->IsMachineInstruction()) { continue; } @@ -1581,8 +1590,10 @@ void ExtendMovPattern::Optimize(Insn &insn) void CopyRegProp::Run() { - FOR_ALL_BB(bb, &cgFunc) { - FOR_BB_INSNS(insn, bb) { + FOR_ALL_BB(bb, &cgFunc) + { + FOR_BB_INSNS(insn, bb) + { if (!insn->IsMachineInstruction()) { continue; } @@ -1703,7 +1714,8 @@ void CopyRegProp::VaildateImplicitCvt(RegOperand &destReg, const RegOperand &src void RedundantPhiProp::Run() { - FOR_ALL_BB(bb, &cgFunc) { + FOR_ALL_BB(bb, &cgFunc) + { for (auto phiIt : bb->GetPhiInsns()) { Init(); if (!CheckCondition(*phiIt.second)) { @@ -1791,8 +1803,10 @@ void ValidBitNumberProp::Optimize(Insn &insn) void ValidBitNumberProp::Run() { - FOR_ALL_BB(bb, &cgFunc) { - FOR_BB_INSNS(insn, bb) { + FOR_ALL_BB(bb, &cgFunc) + { + FOR_BB_INSNS(insn, bb) + { if (!insn->IsMachineInstruction()) { continue; } @@ -1807,8 +1821,10 @@ void ValidBitNumberProp::Run() void FpSpConstProp::Run() { - FOR_ALL_BB(bb, &cgFunc) { - FOR_BB_INSNS(insn, bb) { + FOR_ALL_BB(bb, &cgFunc) + { + FOR_BB_INSNS(insn, bb) + { if (!insn->IsMachineInstruction()) { continue; } @@ -2443,8 +2459,10 @@ void A64PregCopyPattern::Optimize(Insn &insn) void A64PregCopyPattern::Run() { - FOR_ALL_BB(bb, &cgFunc) { - FOR_BB_INSNS(insn, bb) { + FOR_ALL_BB(bb, &cgFunc) + { + FOR_BB_INSNS(insn, bb) + { if (!insn->IsMachineInstruction()) { continue; } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_schedule.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_schedule.cpp index 351a57df3aaa14ff4f1e0e7cdf0de1e5c381584e..f97a3d65945439878eaa5cb5628f1ed34fb044f1 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_schedule.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_schedule.cpp @@ -18,6 +18,7 @@ #include "aarch64_cg.h" #include "aarch64_operand.h" #include "aarch64_dependence.h" +#include "file_utils.h" #include "pressure.h" /* @@ -31,12 +32,13 @@ */ namespace maplebe { namespace { -constexpr uint32 kClinitAdvanceCycle = 10; -constexpr uint32 kAdrpLdrAdvanceCycle = 2; -constexpr uint32 kClinitTailAdvanceCycle = 4; constexpr uint32 kSecondToLastNode = 2; } // namespace +constexpr uint32 kClinitAdvanceCycle = 12; +constexpr uint32 kAdrpLdrAdvanceCycle = 4; +constexpr uint32 kClinitTailAdvanceCycle = 6; + uint32 AArch64Schedule::maxUnitIndex = 0; /* reserve two register for special purpose */ int AArch64Schedule::intRegPressureThreshold = static_cast(R27 - R0); @@ -97,7 +99,7 @@ bool AArch64Schedule::CanCombine(const Insn &insn) const DEBUG_ASSERT(insn.GetOperand(1).IsMemoryAccessOperand(), "expects mem operands"); auto &memOpnd = static_cast(insn.GetOperand(1)); MemOperand::AArch64AddressingMode addrMode = memOpnd.GetAddrMode(); - if ((addrMode != MemOperand::kAddrModeBOi) || !memOpnd.IsIntactIndexed()) { + if (addrMode != MemOperand::kAddrModeBOi) { return false; } @@ -151,7 +153,7 @@ void AArch64Schedule::MemoryAccessPairOpt() FindAndCombineMemoryAccessPair(memList); } readNode = memList[0]; - memList.erase(memList.begin()); + memList.erase(memList.cbegin()); } /* schedule readNode */ @@ -161,7 +163,7 @@ void AArch64Schedule::MemoryAccessPairOpt() /* add readNode's succs to readyList or memList. */ for (auto succLink : readNode->GetSuccs()) { DepNode &succNode = succLink->GetTo(); - succNode.DescreaseValidPredsSize(); + succNode.DecreaseValidPredsSize(); if (succNode.GetValidPredsSize() == 0) { DEBUG_ASSERT(succNode.GetState() == kNormal, "schedule state should be kNormal"); succNode.SetState(kReady); @@ -272,7 +274,7 @@ uint32 AArch64Schedule::GetNextSepIndex() const /* Do register pressure schduling. */ void AArch64Schedule::RegPressureScheduling(BB &bb, MapleVector &nodes) { - RegPressureSchedule *regSchedule = memPool.New(cgFunc, alloc); + auto *regSchedule = memPool.New(cgFunc, alloc); /* * Get physical register amount currently * undef, Int Reg, Float Reg, Flag Reg @@ -296,20 +298,20 @@ uint32 AArch64Schedule::ComputeEstart(uint32 cycle) /* Check validPredsSize. */ for (uint32 i = lastSeparatorIndex; i <= maxIndex; ++i) { DepNode *node = nodes[i]; - [[maybe_unused]] int32 schedNum = 0; + int32 schedNum = 0; for (const auto *predLink : node->GetPreds()) { if (predLink->GetFrom().GetState() == kScheduled) { ++schedNum; } } - DEBUG_ASSERT((node->GetPreds().size() - schedNum) == node->GetValidPredsSize(), "validPredsSize error."); + CHECK_FATAL((node->GetPreds().size() - schedNum) == node->GetValidPredsSize(), "validPredsSize error."); } } DEBUG_ASSERT(nodes[maxIndex]->GetType() == kNodeTypeSeparator, "CG internal error, nodes[maxIndex] should be a separator node."); - (void)readyNodes.insert(readyNodes.begin(), readyList.begin(), readyList.end()); + (void)readyNodes.insert(readyNodes.cbegin(), readyList.cbegin(), readyList.cend()); uint32 maxEstart = cycle; for (uint32 i = lastSeparatorIndex; i <= maxIndex; ++i) { @@ -326,7 +328,7 @@ uint32 AArch64Schedule::ComputeEstart(uint32 cycle) while (!readyNodes.empty()) { DepNode *node = readyNodes.front(); - readyNodes.erase(readyNodes.begin()); + readyNodes.erase(readyNodes.cbegin()); for (const auto *succLink : node->GetSuccs()) { DepNode &succNode = succLink->GetTo(); @@ -368,7 +370,7 @@ void AArch64Schedule::ComputeLstart(uint32 maxEstart) readyNodes.emplace_back(nodes[maxIndex]); while (!readyNodes.empty()) { DepNode *node = readyNodes.front(); - readyNodes.erase(readyNodes.begin()); + readyNodes.erase(readyNodes.cbegin()); for (const auto *predLink : node->GetPreds()) { DepNode &predNode = predLink->GetFrom(); if (predNode.GetState() == kScheduled) { @@ -394,117 +396,18 @@ void AArch64Schedule::UpdateELStartsOnCycle(uint32 cycle) ComputeLstart(ComputeEstart(cycle)); } -/* - * If all unit of this node need when it be scheduling is free, this node can be scheduled, - * Return true. - */ -bool DepNode::CanBeScheduled() const -{ - for (uint32 i = 0; i < unitNum; ++i) { - Unit *unit = units[i]; - if (unit != nullptr) { - if (!unit->IsFree(i)) { - return false; - } - } - } - return true; -} - -/* Mark those unit that this node need occupy unit when it is being scheduled. */ -void DepNode::OccupyUnits() -{ - for (uint32 i = 0; i < unitNum; ++i) { - Unit *unit = units[i]; - if (unit != nullptr) { - unit->Occupy(*insn, i); - } - } -} - -/* Get unit kind of this node's units[0]. */ -uint32 DepNode::GetUnitKind() const -{ - uint32 retValue = 0; - if ((units == nullptr) || (units[0] == nullptr)) { - return retValue; - } - - switch (units[0]->GetUnitId()) { - case kUnitIdSlotD: - retValue |= kUnitKindSlot0; - break; - case kUnitIdAgen: - case kUnitIdSlotSAgen: - retValue |= kUnitKindAgen; - break; - case kUnitIdSlotDAgen: - retValue |= kUnitKindAgen; - retValue |= kUnitKindSlot0; - break; - case kUnitIdHazard: - case kUnitIdSlotSHazard: - retValue |= kUnitKindHazard; - break; - case kUnitIdCrypto: - retValue |= kUnitKindCrypto; - break; - case kUnitIdMul: - case kUnitIdSlotSMul: - retValue |= kUnitKindMul; - break; - case kUnitIdDiv: - retValue |= kUnitKindDiv; - break; - case kUnitIdBranch: - case kUnitIdSlotSBranch: - retValue |= kUnitKindBranch; - break; - case kUnitIdStAgu: - retValue |= kUnitKindStAgu; - break; - case kUnitIdLdAgu: - retValue |= kUnitKindLdAgu; - break; - case kUnitIdFpAluS: - case kUnitIdFpAluD: - retValue |= kUnitKindFpAlu; - break; - case kUnitIdFpMulS: - case kUnitIdFpMulD: - retValue |= kUnitKindFpMul; - break; - case kUnitIdFpDivS: - case kUnitIdFpDivD: - retValue |= kUnitKindFpDiv; - break; - case kUnitIdSlot0LdAgu: - retValue |= kUnitKindSlot0; - retValue |= kUnitKindLdAgu; - break; - case kUnitIdSlot0StAgu: - retValue |= kUnitKindSlot0; - retValue |= kUnitKindStAgu; - break; - default: - break; - } - - return retValue; -} - /* Count unit kinds to an array. Each element of the array indicates the unit kind number of a node set. */ void AArch64Schedule::CountUnitKind(const DepNode &depNode, uint32 array[], const uint32 arraySize) const { (void)arraySize; DEBUG_ASSERT(arraySize >= kUnitKindLast, "CG internal error. unit kind number is not correct."); uint32 unitKind = depNode.GetUnitKind(); - int32 index = static_cast(__builtin_ffs(unitKind)); - while (index) { - DEBUG_ASSERT(static_cast(index) < kUnitKindLast, "CG internal error. index error."); + uint32 index = static_cast(__builtin_ffs(static_cast(unitKind))); + while (index != 0) { + DEBUG_ASSERT(index < kUnitKindLast, "CG internal error. index error."); ++array[index]; unitKind &= ~(1u << (index - 1u)); - index = __builtin_ffs(unitKind); + index = static_cast(__builtin_ffs(static_cast(unitKind))); } } @@ -512,14 +415,14 @@ void AArch64Schedule::CountUnitKind(const DepNode &depNode, uint32 array[], cons bool AArch64Schedule::IfUseUnitKind(const DepNode &depNode, uint32 index) { uint32 unitKind = depNode.GetUnitKind(); - int32 idx = static_cast(__builtin_ffs(unitKind)); - while (idx) { + uint32 idx = static_cast(__builtin_ffs(static_cast(unitKind))); + while (idx != 0) { DEBUG_ASSERT(index < kUnitKindLast, "CG internal error. index error."); - if (idx == static_cast(index)) { + if (idx == index) { return true; } unitKind &= ~(1u << (idx - 1u)); - idx = __builtin_ffs(unitKind); + idx = static_cast(__builtin_ffs(static_cast(unitKind))); } return false; @@ -618,9 +521,9 @@ void AArch64Schedule::SelectNode(AArch64ScheduleProcessInfo &scheduleInfo) } } /* The priority of free-reg node is higher than pipeline */ - while (!targetNode->CanBeScheduled()) { + while (!targetNode->IsResourceIdle()) { scheduleInfo.IncCurrCycle(); - mad->AdvanceCycle(); + mad->AdvanceOneCycleForAll(); } if (GetConsiderRegPressure() && !scheduleInfo.IsFirstSeparator()) { UpdateLiveRegSet(scheduleInfo, *targetNode); @@ -654,7 +557,7 @@ void AArch64Schedule::SelectNode(AArch64ScheduleProcessInfo &scheduleInfo) UpdateAdvanceCycle(scheduleInfo, *targetNode); } -void AArch64Schedule::UpdateAdvanceCycle(AArch64ScheduleProcessInfo &scheduleInfo, const DepNode &targetNode) +void AArch64Schedule::UpdateAdvanceCycle(AArch64ScheduleProcessInfo &scheduleInfo, const DepNode &targetNode) const { switch (targetNode.GetInsn()->GetLatencyType()) { case kLtClinit: @@ -683,11 +586,11 @@ void AArch64Schedule::UpdateAdvanceCycle(AArch64ScheduleProcessInfo &scheduleInf * Advance mad's cycle until info's advanceCycle equal zero, * and then clear info's availableReadyList. */ -void AArch64Schedule::UpdateScheduleProcessInfo(AArch64ScheduleProcessInfo &info) +void AArch64Schedule::UpdateScheduleProcessInfo(AArch64ScheduleProcessInfo &info) const { while (info.GetAdvanceCycle() > 0) { info.IncCurrCycle(); - mad->AdvanceCycle(); + mad->AdvanceOneCycleForAll(); info.DecAdvanceCycle(); } info.ClearAvailableReadyList(); @@ -703,7 +606,7 @@ bool AArch64Schedule::CheckSchedulable(AArch64ScheduleProcessInfo &info) const if (GetConsiderRegPressure()) { info.PushElemIntoAvailableReadyList(node); } else { - if (node->CanBeScheduled() && node->GetEStart() <= info.GetCurrCycle()) { + if (node->IsResourceIdle() && node->GetEStart() <= info.GetCurrCycle()) { info.PushElemIntoAvailableReadyList(node); } } @@ -714,7 +617,7 @@ bool AArch64Schedule::CheckSchedulable(AArch64ScheduleProcessInfo &info) const /* * Calculate estimated machine cycle count for an input node series */ -int AArch64Schedule::CalSeriesCycles(const MapleVector &nodes) +int AArch64Schedule::CalSeriesCycles(const MapleVector &nodes) const { int currentCycle = 0; /* after an instruction is issued, the minimum cycle count for the next instruction is 1 */ @@ -774,10 +677,11 @@ uint32 AArch64Schedule::DoSchedule() DEBUG_ASSERT(scheduleInfo.SizeOfScheduledNodes() == nodes.size(), "CG internal error, Not all nodes scheduled."); nodes.clear(); - (void)nodes.insert(nodes.begin(), scheduleInfo.GetScheduledNodes().begin(), scheduleInfo.GetScheduledNodes().end()); + (void)nodes.insert(nodes.cbegin(), scheduleInfo.GetScheduledNodes().cbegin(), + scheduleInfo.GetScheduledNodes().cend()); /* the second to last node is the true last node, because the last is kNodeTypeSeparator node */ - DEBUG_ASSERT(nodes.size() - 2 >= 0, "size of nodes should be greater than or equal 2"); // size not less than 2 - return (nodes[nodes.size() - 2]->GetSchedCycle()); // size-2 get the second to last node + DEBUG_ASSERT(nodes.size() - 2 >= 0, "size of nodes should be greater than or equal 2"); // size not less than 2 + return (nodes[nodes.size() - 2]->GetSchedCycle()); // size-2 get the second to last node } struct RegisterInfoUnit { @@ -787,7 +691,7 @@ struct RegisterInfoUnit { uint32 ccRegNum = 0; }; -RegisterInfoUnit GetDepNodeDefType(const DepNode &depNode, CGFunc &f) +RegisterInfoUnit GetDepNodeDefType(const DepNode &depNode, const CGFunc &f) { RegisterInfoUnit rIU; for (auto defRegNO : depNode.GetDefRegnos()) { @@ -835,7 +739,7 @@ AArch64Schedule::CSRResult AArch64Schedule::DoCSR(DepNode &node1, DepNode &node2 } } } - auto FindFreeRegNode = [&](bool isInt) -> CSRResult { + auto findFreeRegNode = [&scheduleInfo, &node1, &node2](bool isInt) -> CSRResult { auto freeRegNodes = isInt ? scheduleInfo.GetFreeIntRegNodeSet() : scheduleInfo.GetFreeFpRegNodeSet(); if (freeRegNodes.find(&node1) != freeRegNodes.end() && freeRegNodes.find(&node2) == freeRegNodes.end()) { return kNode1; @@ -846,13 +750,13 @@ AArch64Schedule::CSRResult AArch64Schedule::DoCSR(DepNode &node1, DepNode &node2 return kDoCSP; }; if (static_cast(scheduleInfo.SizeOfIntLiveRegSet()) >= intRegPressureThreshold) { - if (FindFreeRegNode(true) != kDoCSP) { - return FindFreeRegNode(true); + if (findFreeRegNode(true) != kDoCSP) { + return findFreeRegNode(true); } } if (static_cast(scheduleInfo.SizeOfFpLiveRegSet()) >= fpRegPressureThreshold) { - if (FindFreeRegNode(false) != kDoCSP) { - return FindFreeRegNode(false); + if (findFreeRegNode(false) != kDoCSP) { + return findFreeRegNode(false); } } @@ -950,7 +854,7 @@ bool AArch64Schedule::CompareDepNode(DepNode &node1, DepNode &node2, AArch64Sche /* * Calculate number of every unit that used by avaliableReadyList's nodes and save the max in maxUnitIndex */ -void AArch64Schedule::CalculateMaxUnitKindCount(ScheduleProcessInfo &scheduleInfo) +void AArch64Schedule::CalculateMaxUnitKindCount(ScheduleProcessInfo &scheduleInfo) const { uint32 unitKindCount[kUnitKindLast] = {0}; for (auto node : scheduleInfo.GetAvailableReadyList()) { @@ -1051,14 +955,14 @@ uint32 AArch64Schedule::SimulateOnly() for (uint32 i = 0; i < nodes.size();) { while (advanceCycle > 0) { ++currCycle; - mad->AdvanceCycle(); + mad->AdvanceOneCycleForAll(); --advanceCycle; } DepNode *targetNode = nodes[i]; - if ((currCycle >= targetNode->GetEStart()) && targetNode->CanBeScheduled()) { + if ((currCycle >= targetNode->GetEStart()) && targetNode->IsResourceIdle()) { targetNode->SetSimulateCycle(currCycle); - targetNode->OccupyUnits(); + targetNode->OccupyRequiredUnits(); /* Update estart. */ for (auto succLink : targetNode->GetSuccs()) { @@ -1113,6 +1017,10 @@ void AArch64Schedule::FinalizeScheduling(BB &bb, const DepAnalysis &depAnalysis) } bb.AppendInsn(*comment); } + /* Append cfi instructions. */ + for (auto cfi : node->GetCfiInsns()) { + bb.AppendInsn(*cfi); + } /* Append insn. */ if (!node->GetClinitInsns().empty()) { for (auto clinit : node->GetClinitInsns()) { @@ -1124,11 +1032,6 @@ void AArch64Schedule::FinalizeScheduling(BB &bb, const DepAnalysis &depAnalysis) } bb.AppendInsn(*node->GetInsn()); } - - /* Append cfi instructions. */ - for (auto cfi : node->GetCfiInsns()) { - bb.AppendInsn(*cfi); - } } bb.SetLastLoc(prevLocInsn); @@ -1153,7 +1056,8 @@ void AArch64Schedule::IterateBruteForce(DepNode &targetNode, MapleVectorGetAllUnitsSize(), "CG internal error."); - std::vector occupyTable; + constexpr int32 bitSetLength = 32; + std::vector> occupyTable; occupyTable.resize(unitSize, 0); mad->SaveStates(occupyTable, unitSize); @@ -1164,7 +1068,7 @@ void AArch64Schedule::IterateBruteForce(DepNode &targetNode, MapleVector tempList = readyList; EraseNodeFromNodeList(targetNode, tempList); - targetNode.OccupyUnits(); + targetNode.OccupyRequiredUnits(); /* Update readyList. */ UpdateReadyList(targetNode, tempList, true); @@ -1202,7 +1106,7 @@ void AArch64Schedule::IterateBruteForce(DepNode &targetNode, MapleVector tempAvailableList; while (advanceCycle > 0) { ++currCycle; - mad->AdvanceCycle(); + mad->AdvanceOneCycleForAll(); --advanceCycle; } /* Check EStart. */ @@ -1220,7 +1124,7 @@ void AArch64Schedule::IterateBruteForce(DepNode &targetNode, MapleVectorCanBeScheduled()) { + if (node->IsResourceIdle()) { availableReadyList.emplace_back(node); } } @@ -1306,7 +1210,7 @@ void AArch64Schedule::UpdateReadyList(DepNode &targetNode, MapleVectorGetTo(); - succNode.DescreaseValidPredsSize(); + succNode.DecreaseValidPredsSize(); if (succNode.GetValidPredsSize() == 0) { readyList.emplace_back(&succNode); succNode.SetState(kReady); @@ -1385,7 +1289,7 @@ void AArch64Schedule::GenerateDot(const BB &bb, const MapleVector &no fileName.append(str); fileName.append("_dep_graph.dot"); - dgFile.open(fileName.c_str(), std::ios::trunc); + dgFile.open(FileUtils::GetRealPath(fileName), std::ios::trunc); if (!dgFile.is_open()) { LogInfo::MapleLogger(kLlWarn) << "fileName:" << fileName << " open failure.\n"; return; @@ -1419,7 +1323,7 @@ void AArch64Schedule::GenerateDot(const BB &bb, const MapleVector &no std::cout.rdbuf(coutBuf); } -RegType AArch64ScheduleProcessInfo::GetRegisterType(CGFunc &f, regno_t regNO) +RegType AArch64ScheduleProcessInfo::GetRegisterType(const CGFunc &f, regno_t regNO) { if (AArch64isa::IsPhysicalRegister(regNO)) { if (AArch64isa::IsGPRegister(static_cast(regNO))) { @@ -1436,7 +1340,7 @@ RegType AArch64ScheduleProcessInfo::GetRegisterType(CGFunc &f, regno_t regNO) } } -void AArch64ScheduleProcessInfo::VaryLiveRegSet(CGFunc &f, regno_t regNO, bool isInc) +void AArch64ScheduleProcessInfo::VaryLiveRegSet(const CGFunc &f, regno_t regNO, bool isInc) { RegType registerTy = GetRegisterType(f, regNO); if (registerTy == kRegTyInt || registerTy == kRegTyVary) { @@ -1447,7 +1351,7 @@ void AArch64ScheduleProcessInfo::VaryLiveRegSet(CGFunc &f, regno_t regNO, bool i /* consider other type register */ } -void AArch64ScheduleProcessInfo::VaryFreeRegSet(CGFunc &f, std::set regNOs, DepNode &node) +void AArch64ScheduleProcessInfo::VaryFreeRegSet(const CGFunc &f, std::set regNOs, DepNode &node) { for (auto regNO : regNOs) { RegType registerTy = GetRegisterType(f, regNO); @@ -1540,8 +1444,14 @@ void AArch64Schedule::ListScheduling(bool beforeRA) RegPressure::SetMaxRegClassNum(kRegisterLast); } depAnalysis = memPool.New(cgFunc, memPool, *mad, beforeRA); - - FOR_ALL_BB(bb, &cgFunc) { + FOR_ALL_BB(bb, &cgFunc) + { + if (bb->IsUnreachable()) { + continue; + } + if (bb->IsAtomicBuiltInBB()) { + continue; + } depAnalysis->Run(*bb, nodes); if (LIST_SCHED_DUMP_REF) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfi.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfi.cpp index 450d6b996ef71d4213493cb6517b5cd558ff844f..e76fe19ef0d63159f6bce0a6af3ca2a1c8a59184 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfi.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfi.cpp @@ -112,12 +112,3 @@ void CFIOpndEmitVisitor::Visit(LabelOperand *v) } } } /* namespace cfi */ - -namespace maplebe { -bool CgGenCfi::PhaseRun(maplebe::CGFunc &f) -{ - f.GenerateCfiPrologEpilog(); - return true; -} -MAPLE_TRANSFORM_PHASE_REGISTER(CgGenCfi, gencfi) -} /* namespace maplebe */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfi_generator.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfi_generator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ef0caf988e3215c4e7bf5622bf6d0819fbc9540 --- /dev/null +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cfi_generator.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "cfi_generator.h" +#include "cgfunc.h" +#if TARGAARCH64 +#include "aarch64_cfi_generator.h" +#include "aarch64_cgfunc.h" +#endif + +namespace maplebe { +Insn *GenCfi::FindStackDefInsn(BB &bb) const +{ + FOR_BB_INSNS(insn, &bb) + { + if (insn->IsStackDef()) { + return insn; + } + } + return nullptr; +} + +Insn *GenCfi::FinsStackRevertInsn(BB &bb) const +{ + FOR_BB_INSNS_REV(insn, &bb) + { + if (insn->IsStackRevert()) { + return insn; + } + } + return nullptr; +} + +Insn *GenCfi::InsertCFIDefCfaOffset(BB &bb, Insn &insn, int32 &cfiOffset) +{ + cfiOffset = AddtoOffsetFromCFA(cfiOffset); + Insn &cfiInsn = cgFunc.GetInsnBuilder() + ->BuildCfiInsn(cfi::OP_CFI_def_cfa_offset) + .AddOpndChain(cgFunc.CreateCfiImmOperand(cfiOffset, k64BitSize)); + (void)bb.InsertInsnAfter(insn, cfiInsn); + cgFunc.SetDbgCallFrameOffset(cfiOffset); + return &cfiInsn; +} + +void GenCfi::GenerateStartDirective(BB &bb) +{ + Insn &startProcInsn = cgFunc.GetInsnBuilder()->BuildCfiInsn(cfi::OP_CFI_startproc); + if (bb.GetFirstInsn() != nullptr) { + (void)bb.InsertInsnBefore(*bb.GetFirstInsn(), startProcInsn); + } else { + bb.AppendInsn(startProcInsn); + } + +#ifndef ONLY_C +#if !defined(TARGARM32) + /* + * always generate ".cfi_personality 155, DW.ref.__mpl_personality_v0" for Java methods. + * we depend on this to tell whether it is a java method. (maybe we can get a function attribute to determine it) + */ + if (cgFunc.GetFunction().IsJava()) { + Insn &personality = cgFunc.GetInsnBuilder() + ->BuildCfiInsn(cfi::OP_CFI_personality_symbol) + .AddOpndChain(cgFunc.CreateCfiImmOperand(EHFunc::kTypeEncoding, k8BitSize)) + .AddOpndChain(cgFunc.CreateCfiStrOperand("DW.ref.__mpl_personality_v0")); + bb.InsertInsnAfter(startProcInsn, personality); + } +#endif +#endif +} + +void GenCfi::GenerateEndDirective(BB &bb) +{ + bb.AppendInsn(cgFunc.GetInsnBuilder()->BuildCfiInsn(cfi::OP_CFI_endproc)); +} + +void GenCfi::GenerateRegisterStateDirective(BB &bb) +{ + if (cg.GetMIRModule()->IsCModule()) { + return; + } + + if (&bb == cgFunc.GetLastBB() || bb.GetNext() == nullptr) { + return; + } + + BB *nextBB = bb.GetNext(); + do { + if (nextBB == cgFunc.GetLastBB() || !nextBB->IsEmpty()) { + break; + } + nextBB = nextBB->GetNext(); + } while (nextBB != nullptr); + + if (nextBB != nullptr && !nextBB->IsEmpty()) { + bb.InsertInsnBegin(cgFunc.GetInsnBuilder()->BuildCfiInsn(cfi::OP_CFI_remember_state)); + nextBB->InsertInsnBegin(cgFunc.GetInsnBuilder()->BuildCfiInsn(cfi::OP_CFI_restore_state)); + } +} + +void GenCfi::InsertFirstLocation(BB &bb) +{ + MIRSymbol *fSym = GlobalTables::GetGsymTable().GetSymbolFromStidx(cgFunc.GetFunction().GetStIdx().Idx()); + + if (fSym == nullptr || !cg.GetCGOptions().WithLoc() || !cg.GetMIRModule()->IsCModule() || + (fSym->GetSrcPosition().FileNum() == 0)) { + return; + } + + uint32 fileNum = fSym->GetSrcPosition().FileNum(); + uint32 lineNum = fSym->GetSrcPosition().LineNum(); + uint32 columnNum = fSym->GetSrcPosition().Column(); + (void)(bb.InsertInsnBefore(*bb.GetFirstInsn(), cgFunc.BuildLocInsn(fileNum, lineNum, columnNum))); +} + +void GenCfi::Run() +{ + auto *startBB = cgFunc.GetFirstBB(); + GenerateStartDirective(*startBB); + InsertFirstLocation(*startBB); + + if (cgFunc.GetHasProEpilogue()) { + FOR_ALL_BB(bb, &cgFunc) + { + auto *stackDefInsn = FindStackDefInsn(*bb); + if (stackDefInsn != nullptr) { + GenerateRegisterSaveDirective(*bb, *stackDefInsn); + } + auto *stackRevertInsn = FinsStackRevertInsn(*bb); + if (stackRevertInsn != nullptr) { + GenerateRegisterStateDirective(*bb); + GenerateRegisterRestoreDirective(*bb, *stackRevertInsn); + } + } + } + + GenerateEndDirective(*(cgFunc.GetLastBB())); + if (cgFunc.GetLastBB()->IsUnreachable()) { + cgFunc.SetExitBBLost(true); + } +} + +bool CgGenCfi::PhaseRun(maplebe::CGFunc &f) +{ + GenCfi *genCfi = GetPhaseAllocator()->New(f); + genCfi->Run(); + return true; +} +MAPLE_TRANSFORM_PHASE_REGISTER(CgGenCfi, gencfi) +} /* namespace maplebe */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg.cpp index 9a8904ba85a00ad97f4d08ac0d8b29df0090d573..33dfef6053b3c10c06e4688d892d384cddc7b5ae 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg.cpp @@ -150,11 +150,12 @@ void CG::AddStackGuardvar() chkGuard->SetTyIdx(GlobalTables::GetTypeTable().GetTypeTable()[PTY_u64]->GetTypeIndex()); GlobalTables::GetGsymTable().AddToStringSymbolMap(*chkGuard); - MIRSymbol *chkFunc = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal); - chkFunc->SetNameStrIdx(std::string("__stack_chk_fail")); - chkFunc->SetStorageClass(kScText); - chkFunc->SetSKind(kStFunc); - GlobalTables::GetGsymTable().AddToStringSymbolMap(*chkFunc); + MIRFunction *func = GetMIRModule()->GetMIRBuilder()->GetOrCreateFunction( + "__stack_chk_fail", GlobalTables::GetTypeTable().GetVoid()->GetTypeIndex()); + MIRSymbol *chkFuncSym = func->GetFuncSymbol(); + chkFuncSym->SetAppearsInCode(true); + chkFuncSym->SetStorageClass(kScExtern); + GlobalTables::GetGsymTable().AddToStringSymbolMap(*chkFuncSym); } void CG::SetInstrumentationFunction(const std::string &name) diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_cfg.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_cfg.cpp index 00426e42539237187ae99f60fd7a3839b8079cf6..322772ff8f9c79c13b3bd98385cf77b270efbd8a 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_cfg.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_cfg.cpp @@ -58,7 +58,7 @@ void CGCFG::BuildCFG() case BB::kBBIntrinsic: /* * An intrinsic BB append a MOP_wcbnz instruction at the end, check - * AArch64CGFunc::SelectIntrinCall(IntrinsiccallNode *intrinsiccallNode) for details + * AArch64CGFunc::SelectIntrinsicCall(IntrinsiccallNode *intrinsiccallNode) for details */ CHECK_NULL_FATAL(curBB->GetLastMachineInsn()); if (!curBB->GetLastMachineInsn()->IsBranch()) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_irbuilder.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_irbuilder.cpp index 324a33d679807ca0c58cb05224e1d2ef065c87d6..c4bad40aeccffde31dfc4987842b7a09983a3013 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_irbuilder.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_irbuilder.cpp @@ -93,23 +93,59 @@ ImmOperand &OperandBuilder::CreateImm(uint32 size, int64 value, MemPool *mp) return mp ? *mp->New(value, size, false) : *alloc.New(value, size, false); } +ImmOperand &OperandBuilder::CreateImm(uint32 size, int64 value, bool isSigned, MemPool *mp) +{ + return mp ? *mp->New(value, size, isSigned) : *alloc.New(value, size, isSigned); +} + ImmOperand &OperandBuilder::CreateImm(const MIRSymbol &symbol, int64 offset, int32 relocs, MemPool *mp) { return mp ? *mp->New(symbol, offset, relocs, false) : *alloc.New(symbol, offset, relocs, false); } +OfstOperand &OperandBuilder::CreateOfst(int64 offset, uint32 size, MemPool *mp) +{ + return mp ? *mp->New(offset, size) : *alloc.New(offset, size); +} + MemOperand &OperandBuilder::CreateMem(uint32 size, MemPool *mp) { return mp ? *mp->New(size) : *alloc.New(size); } -MemOperand &OperandBuilder::CreateMem(RegOperand &baseOpnd, int64 offset, uint32 size) +MemOperand &OperandBuilder::CreateMem(RegOperand &baseOpnd, int64 offset, uint32 size, MemPool *mp) +{ + OfstOperand &ofstOperand = CreateOfst(offset, baseOpnd.GetSize()); + if (mp != nullptr) { + return *mp->New(&baseOpnd, &ofstOperand, size); + } + return *alloc.New(&baseOpnd, &ofstOperand, size); +} + +MemOperand &OperandBuilder::CreateMem(uint32 size, RegOperand &baseOpnd, ImmOperand &ofstOperand, MemPool *mp) { - MemOperand *memOprand = &CreateMem(size); - memOprand->SetBaseRegister(baseOpnd); - memOprand->SetOffsetOperand(CreateImm(baseOpnd.GetSize(), offset)); - return *memOprand; + if (mp != nullptr) { + return *mp->New(size, &baseOpnd, nullptr, &ofstOperand, nullptr); + } + return *alloc.New(size, &baseOpnd, nullptr, &ofstOperand, nullptr); +} + +MemOperand &OperandBuilder::CreateMem(uint32 size, RegOperand &baseOpnd, ImmOperand &ofstOperand, + const MIRSymbol &symbol, MemPool *mp) +{ + if (mp != nullptr) { + return *mp->New(MemOperand::kAddrModeLo12Li, size, baseOpnd, nullptr, &ofstOperand, &symbol); + } + return *alloc.New(MemOperand::kAddrModeLo12Li, size, baseOpnd, nullptr, &ofstOperand, &symbol); +} + +BitShiftOperand &OperandBuilder::CreateBitShift(BitShiftOperand::ShiftOp op, uint32 amount, uint32 bitLen, MemPool *mp) +{ + if (mp != nullptr) { + return *mp->New(op, amount, bitLen); + } + return *alloc.New(op, amount, bitLen); } RegOperand &OperandBuilder::CreateVReg(uint32 size, RegType type, MemPool *mp) @@ -141,17 +177,17 @@ FuncNameOperand &OperandBuilder::CreateFuncNameOpnd(MIRSymbol &symbol, MemPool * LabelOperand &OperandBuilder::CreateLabel(const char *parent, LabelIdx idx, MemPool *mp) { - return mp ? *mp->New(parent, idx) : *alloc.New(parent, idx); + return mp ? *mp->New(parent, idx, *mp) : *alloc.New(parent, idx, *alloc.GetMemPool()); } CommentOperand &OperandBuilder::CreateComment(const std::string &s, MemPool *mp) { - return mp ? *mp->New(s, *mp) : *alloc.New(s, *mp); + return mp ? *mp->New(s, *mp) : *alloc.New(s, *alloc.GetMemPool()); } CommentOperand &OperandBuilder::CreateComment(const MapleString &s, MemPool *mp) { - return mp ? *mp->New(s.c_str(), *mp) : *alloc.New(s.c_str(), *mp); + return mp ? *mp->New(s.c_str(), *mp) : *alloc.New(s.c_str(), *alloc.GetMemPool()); } } // namespace maplebe diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_phi_elimination.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_phi_elimination.cpp index 3d57b335df86eb6e6e4d4b0f5cc02b38a19efea1..e76d45bd152b0ba5f4d89a8983429f5a7ba284a3 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_phi_elimination.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cg_phi_elimination.cpp @@ -41,8 +41,12 @@ void PhiEliminate::TranslateTSSAToCSSA() #endif PlaceMovInPredBB(fBBId, CreateMov(tempMovDest, *(phiOpndIt.second))); } - Insn &movInsn = CreateMov(destReg, tempMovDest); - bb->ReplaceInsn(*phiInsnIt.second, movInsn); + if (!destReg.IsOfCC()) { + Insn &movInsn = CreateMov(destReg, tempMovDest); + bb->ReplaceInsn(*phiInsnIt.second, movInsn); + } else { + bb->RemoveInsn(*phiInsnIt.second); + } } } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgfunc.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgfunc.cpp index e19055e743ad6a3054908b5d52dd31923afd64e6..d765a09ba3eebea3637631e71c3fe82ed66c02bc 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgfunc.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/cgfunc.cpp @@ -54,7 +54,7 @@ Operand *HandleConstVal(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc) DEBUG_ASSERT(mirConst != nullptr, "get constval of constvalnode failed"); if (mirConst->GetKind() == kConstInt) { auto *mirIntConst = safe_cast(mirConst); - return cgFunc.SelectIntConst(*mirIntConst); + return cgFunc.SelectIntConst(*mirIntConst, parent); } else if (mirConst->GetKind() == kConstFloatConst) { auto *mirFloatConst = safe_cast(mirConst); return cgFunc.SelectFloatConst(*mirFloatConst, parent); @@ -825,8 +825,6 @@ Operand *HandleIntrinOp(const BaseNode &parent, BaseNode &expr, CGFunc &cgFunc) return cgFunc.SelectCSyncSynchronize(intrinsicopNode); case INTRN_C___atomic_load_n: return cgFunc.SelectCAtomicLoadN(intrinsicopNode); - case INTRN_C___atomic_exchange_n: - return cgFunc.SelectCAtomicExchangeN(intrinsicopNode); case INTRN_C__builtin_return_address: case INTRN_C__builtin_extract_return_addr: return cgFunc.SelectCReturnAddress(intrinsicopNode); @@ -1394,17 +1392,16 @@ void HandleICall(StmtNode &stmt, CGFunc &cgFunc) cgFunc.UpdateFrequency(stmt); auto &icallNode = static_cast(stmt); cgFunc.GetCurBB()->SetHasCall(); - Operand *opnd0 = cgFunc.HandleExpr(stmt, *icallNode.GetNopndAt(0)); - cgFunc.SelectIcall(icallNode, *opnd0); + cgFunc.SelectIcall(icallNode); if (cgFunc.GetCurBB()->GetKind() != BB::kBBFallthru) { cgFunc.SetCurBB(*cgFunc.StartNewBB(icallNode)); } } -void HandleIntrinCall(StmtNode &stmt, CGFunc &cgFunc) +void HandleIntrinsicCall(StmtNode &stmt, CGFunc &cgFunc) { auto &call = static_cast(stmt); - cgFunc.SelectIntrinCall(call); + cgFunc.SelectIntrinsicCall(call); } void HandleDassign(StmtNode &stmt, CGFunc &cgFunc) @@ -1428,8 +1425,8 @@ void HandleDassign(StmtNode &stmt, CGFunc &cgFunc) } Operand *opnd0 = cgFunc.HandleExpr(dassignNode, *rhs); cgFunc.SelectDassign(dassignNode, *opnd0); - if (isSaveRetvalToLocal) { - cgFunc.GetCurBB()->GetLastInsn()->MarkAsSaveRetValToLocal(); + if (isSaveRetvalToLocal && cgFunc.GetCurBB() && cgFunc.GetCurBB()->GetLastMachineInsn()) { + cgFunc.GetCurBB()->GetLastMachineInsn()->MarkAsSaveRetValToLocal(); } } @@ -1454,8 +1451,8 @@ void HandleRegassign(StmtNode &stmt, CGFunc &cgFunc) } Operand *opnd0 = cgFunc.HandleExpr(regAssignNode, *operand); cgFunc.SelectRegassign(regAssignNode, *opnd0); - if (isSaveRetvalToLocal) { - cgFunc.GetCurBB()->GetLastInsn()->MarkAsSaveRetValToLocal(); + if (isSaveRetvalToLocal && cgFunc.GetCurBB() && cgFunc.GetCurBB()->GetLastMachineInsn()) { + cgFunc.GetCurBB()->GetLastMachineInsn()->MarkAsSaveRetValToLocal(); } } @@ -1540,7 +1537,7 @@ void HandleMembar(StmtNode &stmt, CGFunc &cgFunc) return; } cgFunc.SetVolStore(true); - cgFunc.SetVolReleaseInsn(cgFunc.GetCurBB()->GetLastInsn()); + cgFunc.SetVolReleaseInsn(cgFunc.GetCurBB()->GetLastMachineInsn()); } void HandleComment(StmtNode &stmt, CGFunc &cgFunc) @@ -1586,10 +1583,10 @@ void InitHandleStmtFactory() RegisterFactoryFunction(OP_call, HandleCall); RegisterFactoryFunction(OP_icall, HandleICall); RegisterFactoryFunction(OP_icallproto, HandleICall); - RegisterFactoryFunction(OP_intrinsiccall, HandleIntrinCall); - RegisterFactoryFunction(OP_intrinsiccallassigned, HandleIntrinCall); - RegisterFactoryFunction(OP_intrinsiccallwithtype, HandleIntrinCall); - RegisterFactoryFunction(OP_intrinsiccallwithtypeassigned, HandleIntrinCall); + RegisterFactoryFunction(OP_intrinsiccall, HandleIntrinsicCall); + RegisterFactoryFunction(OP_intrinsiccallassigned, HandleIntrinsicCall); + RegisterFactoryFunction(OP_intrinsiccallwithtype, HandleIntrinsicCall); + RegisterFactoryFunction(OP_intrinsiccallwithtypeassigned, HandleIntrinsicCall); RegisterFactoryFunction(OP_dassign, HandleDassign); RegisterFactoryFunction(OP_dassignoff, HandleDassignoff); RegisterFactoryFunction(OP_regassign, HandleRegassign); @@ -1629,7 +1626,8 @@ CGFunc::CGFunc(MIRModule &mod, CG &cg, MIRFunction &mirFunc, BECommon &beCommon, vregsToPregsMap(std::less(), allocator.Adapter()), stackMapInsns(allocator.Adapter()), hasVLAOrAlloca(mirFunc.HasVlaOrAlloca()), - dbgCallFrameLocations(allocator.Adapter()), + dbgParamCallFrameLocations(allocator.Adapter()), + dbgLocalCallFrameLocations(allocator.Adapter()), cg(&cg), mirModule(mod), memPool(&memPool), @@ -1757,6 +1755,16 @@ void CGFunc::RemoveUnreachableBB() } } +Insn &CGFunc::BuildLocInsn(int64 fileNum, int64 lineNum, int64 columnNum) +{ + Operand *o0 = CreateDbgImmOperand(fileNum); + Operand *o1 = CreateDbgImmOperand(lineNum); + Operand *o2 = CreateDbgImmOperand(columnNum); + Insn &loc = + GetInsnBuilder()->BuildDbgInsn(mpldbg::OP_DBG_loc).AddOpndChain(*o0).AddOpndChain(*o1).AddOpndChain(*o2); + return loc; +} + void CGFunc::GenerateLoc(StmtNode *stmt, unsigned &lastSrcLoc, unsigned &lastMplLoc) { /* insert Insn for .loc before cg for the stmt */ @@ -2275,7 +2283,7 @@ void CGFunc::HandleFunction() } } -void CGFunc::AddDIESymbolLocation(const MIRSymbol *sym, SymbolAlloc *loc) +void CGFunc::AddDIESymbolLocation(const MIRSymbol *sym, SymbolAlloc *loc, bool isParam) { DEBUG_ASSERT(debugInfo != nullptr, "debugInfo is null!"); DEBUG_ASSERT(loc->GetMemSegment() != nullptr, "only support those variable that locate at stack now"); @@ -2288,7 +2296,7 @@ void CGFunc::AddDIESymbolLocation(const MIRSymbol *sym, SymbolAlloc *loc) CHECK_FATAL(exprloc != nullptr, "exprloc is null in CGFunc::AddDIESymbolLocation"); exprloc->SetSymLoc(loc); - GetDbgCallFrameLocations().push_back(exprloc); + GetDbgCallFrameLocations(isParam).push_back(exprloc); } void CGFunc::DumpCFG() const @@ -2433,6 +2441,23 @@ void CGFunc::DumpCFGToDot(const std::string &fileNamePrefix) file << "}" << std::endl; } +// Cgirverify phase function: all insns will be verified before cgemit. +void CGFunc::VerifyAllInsn() +{ + FOR_ALL_BB(bb, this) + { + FOR_BB_INSNS(insn, bb) + { + if (!VERIFY_INSN(insn)) { + LogInfo::MapleLogger() << "Illegal insn is:\n"; + insn->Dump(); + LogInfo::MapleLogger() << "Function name is:\n" << GetName() << "\n"; + CHECK_FATAL_FALSE("The problem is illegal insn, info is above."); + } + } + } +} + void CGFunc::PatchLongBranch() { for (BB *bb = firstBB->GetNext(); bb != nullptr; bb = bb->GetNext()) { @@ -2479,4 +2504,14 @@ bool CgFixCFLocOsft::PhaseRun(maplebe::CGFunc &f) return false; } MAPLE_TRANSFORM_PHASE_REGISTER(CgFixCFLocOsft, dbgfixcallframeoffsets) + +bool CgVerify::PhaseRun(maplebe::CGFunc &f) +{ + f.VerifyAllInsn(); + if (!f.GetCG()->GetCGOptions().DoEmitCode() || f.GetCG()->GetCGOptions().DoDumpCFG()) { + f.DumpCFG(); + } + return false; +} +MAPLE_TRANSFORM_PHASE_REGISTER(CgVerify, cgirverify) } /* namespace maplebe */ diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/insn.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/insn.cpp index f0f846395a14a2dc57193fd50b6372d96ac3701e..f6e1466420b2873cfb7a030d92b231a5a81c5ca8 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/insn.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/insn.cpp @@ -220,7 +220,6 @@ uint32 Insn::GetMemOpndIdx() const } return opndIdx; } - void Insn::SetMemOpnd(MemOperand *memOpnd) { for (uint32 i = 0; i < static_cast(opnds.size()); ++i) { diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp index dd4909ca432d177815701267c852eb686bdb1882..b739fd2b09eb758751312c5ed6566e302054b518 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/isel.cpp @@ -79,10 +79,8 @@ MOperator GetFastIselMop(Operand::OperandType dTy, Operand::OperandType sTy, Pri return abstract::MOP_undef; } -#define DEF_EXTEND_MAPPING_TBL(TYPE) \ - [](bool isSigned)->MOperator { \ - return isSigned ? abstract::MOP_sext_rr_##TYPE : abstract::MOP_zext_rr_##TYPE; \ - } +#define DEF_EXTEND_MAPPING_TBL(TYPE) \ + [](bool isSigned) -> MOperator { return isSigned ? abstract::MOP_sext_rr_##TYPE : abstract::MOP_zext_rr_##TYPE; } using fromToTy = std::pair; /* std::pair */ #define DEF_USE_EXTEND_MAPPING_TBL(FROMSIZE, TOSIZE) \ { \ @@ -226,7 +224,7 @@ void HandleGoto(StmtNode &stmt, MPISel &iSel) void HandleIntrinCall(StmtNode &stmt, MPISel &iSel) { auto &call = static_cast(stmt); - iSel.SelectIntrinCall(call); + iSel.SelectIntrinsicCall(call); } void HandleRangeGoto(StmtNode &stmt, MPISel &iSel) @@ -275,8 +273,7 @@ void HandleIcall(StmtNode &stmt, MPISel &iSel) { DEBUG_ASSERT(stmt.GetOpCode() == OP_icall || stmt.GetOpCode() == OP_icallproto, "error"); auto &iCallNode = static_cast(stmt); - Operand *opnd0 = iSel.HandleExpr(iCallNode, *iCallNode.Opnd(0)); - iSel.SelectIcall(iCallNode, *opnd0); + iSel.SelectIcall(iCallNode); iSel.SelectCallCommon(stmt, iSel); } @@ -402,7 +399,7 @@ Operand *HandleConstStr(const BaseNode &parent, BaseNode &expr, MPISel &iSel) Operand *HandleTrunc(const BaseNode &parent, BaseNode &expr, MPISel &iSel) { - return iSel.SelectCvt(parent, static_cast(expr), *iSel.HandleExpr(expr, *expr.Opnd(0))); + return iSel.SelectCvt(parent, static_cast(expr), *iSel.HandleExpr(expr, *expr.Opnd(0))); } Operand *HandleConstVal(const BaseNode &parent, BaseNode &expr, MPISel &iSel) @@ -1400,14 +1397,14 @@ Operand *MPISel::SelectAbs(UnaryNode &node, Operand &opnd0) * fabs(x) = x AND 0x7fffffff ffffffff [set sign bit to 0] */ const static uint64 kNaN = 0x7fffffffffffffffUL; - const static double kNaNDouble = *(double*)(&kNaN); + const static double kNaNDouble = *(double *)(&kNaN); const static uint64 kNaNf = 0x7fffffffUL; - const static double kNaNFloat = *(double*)(&kNaNf); + const static double kNaNFloat = *(double *)(&kNaNf); CHECK_FATAL(primType == PTY_f64 || primType == PTY_f32, "niy"); double mask = primType == PTY_f64 ? kNaNDouble : kNaNFloat; - MIRDoubleConst *c = cgFunc->GetMemoryPool()->New(mask, - *GlobalTables::GetTypeTable().GetTypeTable().at(PTY_f64)); + MIRDoubleConst *c = cgFunc->GetMemoryPool()->New( + mask, *GlobalTables::GetTypeTable().GetTypeTable().at(PTY_f64)); Operand *opnd1 = SelectFloatingConst(*c, PTY_f64); RegOperand &resOpnd = @@ -1667,14 +1664,14 @@ Operand *MPISel::SelectRetype(TypeCvtNode &node, Operand &opnd0) return &SelectCopy2Reg(opnd0, toType, fromType); } if (IsPrimitiveInteger(fromType) && IsPrimitiveFloat(toType)) { - RegOperand *resOpnd = &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), - cgFunc->GetRegTyFromPrimTy(toType)); + RegOperand *resOpnd = + &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType)); SelectRetypeFloat(*resOpnd, opnd0, toType, fromType); return &(*resOpnd); } if (IsPrimitiveFloat(fromType) && IsPrimitiveInteger(toType)) { - RegOperand *resOpnd = &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), - cgFunc->GetRegTyFromPrimTy(toType)); + RegOperand *resOpnd = + &cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(toType), cgFunc->GetRegTyFromPrimTy(toType)); SelectRetypeFloat(*resOpnd, opnd0, toType, fromType); return &(*resOpnd); } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/schedule.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/schedule.cpp index 316948f3a48b8ace294d88eb8352a86195d7f972..ad405345fdaac7fe1c466d800a84a235eab6c883 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/schedule.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/schedule.cpp @@ -15,10 +15,10 @@ #if TARGAARCH64 #include "aarch64_schedule.h" -#elif TARGRISCV64 +#elif defined(TARGRISCV64) && TARGRISCV64 #include "riscv64_schedule.h" #endif -#if TARGARM32 +#if defined(TARGARM32) && TARGARM32 #include "arm32_schedule.h" #endif #include "cg.h" @@ -28,13 +28,13 @@ namespace maplebe { /* pressure standard value; pressure under this value will not lead to spill operation */ -static constexpr int g_pressureStandard = 27; +static constexpr int PRESSURE_STANDARD = 27; /* optimistic scheduling option */ -static constexpr bool g_optimisticScheduling = false; +static constexpr bool OPTIMISTIC_SCHEDULING = false; /* brute maximum count limit option */ -static constexpr bool g_bruteMaximumLimit = true; +static constexpr bool BRUTE_MAXIMUM_LIMIT = true; /* brute maximum count */ -static constexpr int g_schedulingMaximumCount = 20000; +static constexpr int SCHEDULING_MAXIMUM_COUNT = 20000; /* ---- RegPressureSchedule function ---- */ void RegPressureSchedule::InitBBInfo(BB &b, MemPool &memPool, const MapleVector &nodes) @@ -59,7 +59,7 @@ RegType RegPressureSchedule::GetRegisterType(regno_t reg) const } /* Get amount of every physical register */ -void RegPressureSchedule::BuildPhyRegInfo(const std::vector ®NumVec) +void RegPressureSchedule::BuildPhyRegInfo(const std::vector ®NumVec) const { FOR_ALL_REGCLASS(i) { @@ -68,22 +68,22 @@ void RegPressureSchedule::BuildPhyRegInfo(const std::vector ®NumVec) } /* Initialize pre-scheduling split point in BB */ -void RegPressureSchedule::initPartialSplitters(const MapleVector &nodes) +void RegPressureSchedule::InitPartialSplitters(const MapleVector &nodes) { bool addFirstAndLastNodeIndex = false; - constexpr uint32 SecondLastNodeIndexFromBack = 2; - constexpr uint32 LastNodeIndexFromBack = 1; - constexpr uint32 FirstNodeIndex = 0; - constexpr uint32 minimumBBSize = 2; + constexpr uint32 kSecondLastNodeIndexFromBack = 2; + constexpr uint32 kLastNodeIndexFromBack = 1; + constexpr uint32 kFirstNodeIndex = 0; + constexpr uint32 kMinimumBBSize = 2; /* Add split point for the last instruction in return BB */ - if (bb->GetKind() == BB::kBBReturn && nodes.size() > minimumBBSize) { - splitterIndexes.emplace_back(nodes.size() - SecondLastNodeIndexFromBack); + if (bb->GetKind() == BB::kBBReturn && nodes.size() > kMinimumBBSize) { + splitterIndexes.emplace_back(nodes.size() - kSecondLastNodeIndexFromBack); addFirstAndLastNodeIndex = true; } /* Add first and last node as split point if needed */ if (addFirstAndLastNodeIndex) { - splitterIndexes.emplace_back(nodes.size() - LastNodeIndexFromBack); - splitterIndexes.emplace_back(FirstNodeIndex); + splitterIndexes.emplace_back(nodes.size() - kLastNodeIndexFromBack); + splitterIndexes.emplace_back(kFirstNodeIndex); } std::sort(splitterIndexes.begin(), splitterIndexes.end(), std::less {}); } @@ -154,7 +154,7 @@ bool RegPressureSchedule::DepNodePriorityCmp(const DepNode *node1, const DepNode int32 numCall1 = node1->GetNumCall(); int32 numCall2 = node2->GetNumCall(); - if (node1->GetIncPressure() == true && node2->GetIncPressure() == true) { + if (node1->GetIncPressure() && node2->GetIncPressure()) { if (numCall1 != numCall2) { return numCall1 > numCall2; } @@ -190,7 +190,7 @@ bool RegPressureSchedule::DepNodePriorityCmp(const DepNode *node1, const DepNode } /* set a node's incPressure is true, when a class register inscrease */ -void RegPressureSchedule::ReCalculateDepNodePressure(DepNode &node) +void RegPressureSchedule::ReCalculateDepNodePressure(const DepNode &node) const { /* if there is a type of register pressure increases, set incPressure as true. */ auto &pressures = node.GetPressure(); @@ -198,7 +198,7 @@ void RegPressureSchedule::ReCalculateDepNodePressure(DepNode &node) } /* calculate the maxDepth of every node in nodes. */ -void RegPressureSchedule::CalculateMaxDepth(const MapleVector &nodes) +void RegPressureSchedule::CalculateMaxDepth(const MapleVector &nodes) const { /* from the last node to first node. */ for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) { @@ -223,7 +223,7 @@ void RegPressureSchedule::CalculateMaxDepth(const MapleVector &nodes) } /* calculate the near of every successor of the node. */ -void RegPressureSchedule::CalculateNear(const DepNode &node) +void RegPressureSchedule::CalculateNear(const DepNode &node) const { for (auto succ : node.GetSuccs()) { DepNode &to = succ->GetTo(); @@ -246,7 +246,7 @@ bool RegPressureSchedule::IsLastUse(const DepNode &node, regno_t regNO) RegList *regList = node.GetRegUses(i); /* - * except the node, if there are insn that has no scheduled in regNO'sregList, + * except the node, if there are insn that has no scheduled in regNO's regList, * then it is not the last time using the regNO, return false. */ while (regList != nullptr) { @@ -261,7 +261,7 @@ bool RegPressureSchedule::IsLastUse(const DepNode &node, regno_t regNO) return true; } -void RegPressureSchedule::CalculatePressure(DepNode &node, regno_t reg, bool def) +void RegPressureSchedule::CalculatePressure(const DepNode &node, regno_t reg, bool def) const { RegType regType = GetRegisterType(reg); /* if def a register, register pressure increase. */ @@ -426,7 +426,7 @@ void RegPressureSchedule::UpdateReadyList(const DepNode &node) if (!partialSet.empty() && (partialSet.find(&succNode) == partialSet.end())) { continue; } - succNode.DescreaseValidPredsSize(); + succNode.DecreaseValidPredsSize(); if (((succ->GetDepType() == kDependenceTypeTrue) || CanSchedule(succNode)) && (succNode.GetState() == kNormal)) { readyList.emplace_back(&succNode); @@ -453,7 +453,7 @@ void RegPressureSchedule::BruteUpdateReadyList(const DepNode &node, std::vector< if (!partialSet.empty() && (partialSet.find(&succNode) == partialSet.end())) { continue; } - succNode.DescreaseValidPredsSize(); + succNode.DecreaseValidPredsSize(); if (((succ->GetDepType() == kDependenceTypeTrue) || CanSchedule(succNode)) && (succNode.GetState() == kNormal)) { readyList.emplace_back(&succNode); @@ -626,7 +626,7 @@ void RegPressureSchedule::DoScheduling(MapleVector &nodes) for (auto node : nodes) { originalNodeSeries.emplace_back(node); } - initPartialSplitters(nodes); + InitPartialSplitters(nodes); #if PRESCHED_DEBUG LogInfo::MapleLogger() << "\n Calculate Pressure Info for Schedule Input Series \n"; #endif @@ -635,7 +635,7 @@ void RegPressureSchedule::DoScheduling(MapleVector &nodes) LogInfo::MapleLogger() << "Original pressure : " << originalPressure << "\n"; #endif /* Original pressure is small enough, skip pre-scheduling */ - if (originalPressure < g_pressureStandard) { + if (originalPressure < PRESSURE_STANDARD) { #if PRESCHED_DEBUG LogInfo::MapleLogger() << "Original pressure is small enough, skip pre-scheduling \n"; #endif @@ -643,7 +643,7 @@ void RegPressureSchedule::DoScheduling(MapleVector &nodes) } if (splitterIndexes.empty()) { LogInfo::MapleLogger() << "No splitter, normal scheduling \n"; - if (!g_optimisticScheduling) { + if (!OPTIMISTIC_SCHEDULING) { HeuristicScheduling(nodes); } else { InitBruteForceScheduling(nodes); @@ -809,7 +809,7 @@ void RegPressureSchedule::PartialScheduling(MapleVector &nodes) void RegPressureSchedule::BruteForceScheduling() { /* stop brute force scheduling when exceeding the count limit */ - if (g_bruteMaximumLimit && (scheduleSeriesCount > g_schedulingMaximumCount)) { + if (BRUTE_MAXIMUM_LIMIT && (scheduleSeriesCount > SCHEDULING_MAXIMUM_COUNT)) { return; } int defaultPressureValue = -1; @@ -910,9 +910,11 @@ void RegPressureSchedule::EmitSchedulingSeries(MapleVector &nodes) void Schedule::InitIDAndLoc() { uint32 id = 0; - FOR_ALL_BB(bb, &cgFunc) { + FOR_ALL_BB(bb, &cgFunc) + { bb->SetLastLoc(bb->GetPrev() ? bb->GetPrev()->GetLastLoc() : nullptr); - FOR_BB_INSNS(insn, bb) { + FOR_BB_INSNS(insn, bb) + { insn->SetId(id++); #if DEBUG insn->AppendComment(" Insn id: " + std::to_string(insn->GetId())); @@ -942,10 +944,10 @@ bool CgPreScheduling::PhaseRun(maplebe::CGFunc &f) live->ResetLiveSet(); Schedule *schedule = nullptr; -#if TARGAARCH64 || TARGRISCV64 +#if (defined(TARGAARCH64) && TARGAARCH64) || (defined(TARGRISCV64) && TARGRISCV64) schedule = GetPhaseAllocator()->New(f, *GetPhaseMemPool(), *live, PhaseName()); #endif -#if TARGARM32 +#if defined(TARGARM32) && TARGARM32 schedule = GetPhaseAllocator()->New(f, *GetPhaseMemPool(), *live, PhaseName()); #endif schedule->ListScheduling(true); @@ -976,10 +978,10 @@ bool CgScheduling::PhaseRun(maplebe::CGFunc &f) live->ResetLiveSet(); Schedule *schedule = nullptr; -#if TARGAARCH64 || TARGRISCV64 +#if (defined(TARGAARCH64) && TARGAARCH64) || (defined(TARGRISCV64) && TARGRISCV64) schedule = GetPhaseAllocator()->New(f, *GetPhaseMemPool(), *live, PhaseName()); #endif -#if TARGARM32 +#if defined(TARGARM32) && TARGARM32 schedule = GetPhaseAllocator()->New(f, *GetPhaseMemPool(), *live, PhaseName()); #endif schedule->ListScheduling(false); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp index 92bebdbf1060e528138fdb57903cfc56ff594c65..0f218b9666f87d6c7c4011c5a4db6172b9880de3 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_MPIsel.cpp @@ -412,8 +412,8 @@ void X64MPIsel::SelectAggCopy(MemOperand &lhs, MemOperand &rhs, uint32 copySize) SelectCopy(memOpndLhs, memOpndRhs, extraTy); } -void X64MPIsel::SelectLibCall(const std::string &funcName, std::vector &opndVec, PrimType primType, - Operand* retOpnd, PrimType retType) +void X64MPIsel::SelectLibCall(const std::string &funcName, std::vector &opndVec, PrimType primType, + Operand *retOpnd, PrimType retType) { /* generate libcall */ std::vector pt(opndVec.size(), primType); @@ -422,7 +422,7 @@ void X64MPIsel::SelectLibCall(const std::string &funcName, std::vector } void X64MPIsel::SelectLibCallNArg(const std::string &funcName, std::vector &opndVec, - std::vector pt, Operand* retOpnd, PrimType retPrimType) + std::vector pt, Operand *retOpnd, PrimType retPrimType) { std::string newName = funcName; MIRSymbol *st = GlobalTables::GetGsymTable().CreateSymbol(kScopeGlobal); @@ -485,7 +485,7 @@ void X64MPIsel::SelectLibCallNArg(const std::string &funcName, std::vectorGetPrimType())); } CHECK_FATAL(retOpnd->IsRegister(), "niy"); - RegOperand *regOpnd = static_cast(retOpnd); + RegOperand *regOpnd = static_cast(retOpnd); regno_t retRegNo = retMech.GetReg0(); if (regOpnd->GetRegisterNumber() != retRegNo) { RegOperand &phyRetOpnd = @@ -501,9 +501,9 @@ Operand *X64MPIsel::SelectFloatingConst(MIRConst &floatingConst, PrimType primTy uint32 labelIdxTmp = cgFunc->GetLabelIdx(); Operand *result = nullptr; if (primType == PTY_f64) { - result = SelectLiteral(static_cast(floatingConst), cgFunc->GetFunction(), labelIdxTmp++); + result = SelectLiteral(static_cast(floatingConst), cgFunc->GetFunction(), labelIdxTmp++); } else { - result = SelectLiteral(static_cast(floatingConst), cgFunc->GetFunction(), labelIdxTmp++); + result = SelectLiteral(static_cast(floatingConst), cgFunc->GetFunction(), labelIdxTmp++); } cgFunc->SetLabelIdx(labelIdxTmp); return result; @@ -643,9 +643,10 @@ void X64MPIsel::SelectCall(CallNode &callNode) cgFunc->AppendStackMapInsn(callInsn); } -void X64MPIsel::SelectIcall(IcallNode &iCallNode, Operand &opnd0) +void X64MPIsel::SelectIcall(IcallNode &iCallNode) { - RegOperand &targetOpnd = SelectCopy2Reg(opnd0, iCallNode.Opnd(0)->GetPrimType()); + Operand *opnd0 = HandleExpr(iCallNode, *iCallNode.GetNopndAt(0)); + RegOperand &targetOpnd = SelectCopy2Reg(*opnd0, iCallNode.Opnd(0)->GetPrimType()); ListOperand ¶mOpnds = cgFunc->GetOpndBuilder()->CreateList(); uint32 fpNum = 0; SelectParmList(iCallNode, paramOpnds, fpNum); @@ -866,10 +867,9 @@ void X64MPIsel::SelectCVaStart(const IntrinsiccallNode &intrnNode) return; } -void X64MPIsel::SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) +void X64MPIsel::SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) { MIRIntrinsicID intrinsic = intrinsiccallNode.GetIntrinsic(); - if (intrinsic == INTRN_C_va_start) { SelectCVaStart(intrinsiccallNode); return; @@ -890,7 +890,7 @@ void X64MPIsel::SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) void X64MPIsel::SelectRangeGoto(RangeGotoNode &rangeGotoNode, Operand &srcOpnd) { MIRType *etype = GlobalTables::GetTypeTable().GetTypeFromTyIdx((TyIdx)PTY_a64); - std::vector sizeArray; + std::vector sizeArray; const SmallCaseVector &switchTable = rangeGotoNode.GetRangeGotoTable(); sizeArray.emplace_back(switchTable.size()); MemPool *memPool = cgFunc->GetMemoryPool(); @@ -1172,17 +1172,18 @@ void X64MPIsel::SelectMpy(Operand &resOpnd, Operand &opnd0, Operand &opnd1, Prim SelectCopy(resOpnd, opnd0, primType); RegOperand ®Opnd1 = SelectCopy2Reg(opnd1, primType); if (IsSignedInteger(primType) || IsUnsignedInteger(primType)) { - X64MOP_t mOp = (bitSize == k64BitSize) - ? x64::MOP_imulq_r_r - : (bitSize == k32BitSize) ? x64::MOP_imull_r_r - : (bitSize == k16BitSize) ? x64::MOP_imulw_r_r : x64::MOP_begin; + X64MOP_t mOp = (bitSize == k64BitSize) ? x64::MOP_imulq_r_r + : (bitSize == k32BitSize) ? x64::MOP_imull_r_r + : (bitSize == k16BitSize) ? x64::MOP_imulw_r_r + : x64::MOP_begin; CHECK_FATAL(mOp != x64::MOP_begin, "NIY mapping"); Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, X64CG::kMd[mOp]); insn.AddOpndChain(regOpnd1).AddOpndChain(resOpnd); cgFunc->GetCurBB()->AppendInsn(insn); } else if (IsPrimitiveFloat(primType)) { - X64MOP_t mOp = (bitSize == k64BitSize) ? x64::MOP_mulfd_r_r : - (bitSize == k32BitSize) ? x64::MOP_mulfs_r_r : x64::MOP_begin; + X64MOP_t mOp = (bitSize == k64BitSize) ? x64::MOP_mulfd_r_r + : (bitSize == k32BitSize) ? x64::MOP_mulfs_r_r + : x64::MOP_begin; CHECK_FATAL(mOp != x64::MOP_begin, "NIY mapping"); Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(mOp, X64CG::kMd[mOp]); insn.AddOpndChain(regOpnd1).AddOpndChain(resOpnd); @@ -1245,10 +1246,10 @@ Operand *X64MPIsel::SelectDivRem(RegOperand &opnd0, RegOperand &opnd1, PrimType bool isSigned = IsSignedInteger(primType); if (isSigned) { /* cdq edx:eax = sign-extend of eax*/ - X64MOP_t cvtMOp = - (bitSize == k64BitSize) - ? x64::MOP_cqo - : (bitSize == k32BitSize) ? x64::MOP_cdq : (bitSize == k16BitSize) ? x64::MOP_cwd : x64::MOP_begin; + X64MOP_t cvtMOp = (bitSize == k64BitSize) ? x64::MOP_cqo + : (bitSize == k32BitSize) ? x64::MOP_cdq + : (bitSize == k16BitSize) ? x64::MOP_cwd + : x64::MOP_begin; CHECK_FATAL(cvtMOp != x64::MOP_begin, "NIY mapping"); Insn &cvtInsn = cgFunc->GetInsnBuilder()->BuildInsn(cvtMOp, raxOpnd, rdxOpnd); cgFunc->GetCurBB()->AppendInsn(cvtInsn); @@ -1257,12 +1258,10 @@ Operand *X64MPIsel::SelectDivRem(RegOperand &opnd0, RegOperand &opnd1, PrimType SelectCopy(rdxOpnd, cgFunc->GetOpndBuilder()->CreateImm(bitSize, 0), primType); } /* div */ - X64MOP_t divMOp = - (bitSize == k64BitSize) - ? (isSigned ? x64::MOP_idivq_r : x64::MOP_divq_r) - : (bitSize == k32BitSize) - ? (isSigned ? x64::MOP_idivl_r : x64::MOP_divl_r) - : (bitSize == k16BitSize) ? (isSigned ? x64::MOP_idivw_r : x64::MOP_divw_r) : x64::MOP_begin; + X64MOP_t divMOp = (bitSize == k64BitSize) ? (isSigned ? x64::MOP_idivq_r : x64::MOP_divq_r) + : (bitSize == k32BitSize) ? (isSigned ? x64::MOP_idivl_r : x64::MOP_divl_r) + : (bitSize == k16BitSize) ? (isSigned ? x64::MOP_idivw_r : x64::MOP_divw_r) + : x64::MOP_begin; CHECK_FATAL(divMOp != x64::MOP_begin, "NIY mapping"); Insn &insn = cgFunc->GetInsnBuilder()->BuildInsn(divMOp, opnd1, raxOpnd, rdxOpnd); cgFunc->GetCurBB()->AppendInsn(insn); @@ -1374,16 +1373,16 @@ void X64MPIsel::SelectCmpFloatEq(RegOperand &resOpnd, Operand &opnd0, Operand &o Insn &setInsn = cgFunc->GetInsnBuilder()->BuildInsn(eqMOp, X64CG::kMd[eqMOp]); auto ®Opnd1 = cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primOpndType), - cgFunc->GetRegTyFromPrimTy(primOpndType)); + cgFunc->GetRegTyFromPrimTy(primOpndType)); SelectCopy(regOpnd1, opnd1, primOpndType); /* CMPEQSD xmm1, xmm2 => CMPSD xmm1, xmm2, 0 */ setInsn.AddOpndChain(opnd0).AddOpndChain(regOpnd1); cgFunc->GetCurBB()->AppendInsn(setInsn); /* set result -> u64/u32 */ - auto tmpResType = (primOpndType == maple::PTY_f64) ? PTY_u64 :PTY_u32; - RegOperand &tmpResOpnd = cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(tmpResType), - cgFunc->GetRegTyFromPrimTy(tmpResType)); + auto tmpResType = (primOpndType == maple::PTY_f64) ? PTY_u64 : PTY_u32; + RegOperand &tmpResOpnd = + cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(tmpResType), cgFunc->GetRegTyFromPrimTy(tmpResType)); SelectRetypeFloat(tmpResOpnd, regOpnd1, tmpResType, primOpndType); /* cvt u64/u32 -> primType */ SelectIntCvt(resOpnd, tmpResOpnd, primResType, tmpResType); @@ -1472,7 +1471,7 @@ Operand *X64MPIsel::SelectCexp(IntrinsicopNode &node, Operand &opnd0, const Base RegOperand ®Opnd0 = SelectCopy2Reg(opnd0, primType); Operand &retReg = cgFunc->GetOpndBuilder()->CreateVReg(GetPrimTypeBitSize(primType), cgFunc->GetRegTyFromPrimTy(primType)); - std::vector opndVec = {®Opnd0}; + std::vector opndVec = {®Opnd0}; SelectLibCall("exp", opndVec, primType, &retReg, primType); return &retReg; } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_cgfunc.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_cgfunc.cpp index e325100aea3c7ff2aa06a6236bdebfbecf139956..45f5c9d8bc4b87d6ab1a16cd0b766ffd3d029fd3 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_cgfunc.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_cgfunc.cpp @@ -147,11 +147,11 @@ void X64CGFunc::SelectCall(CallNode &callNode) { CHECK_FATAL(false, "NIY"); } -void X64CGFunc::SelectIcall(IcallNode &icallNode, Operand &fptrOpnd) +void X64CGFunc::SelectIcall(IcallNode &icallNode) { CHECK_FATAL(false, "NIY"); } -void X64CGFunc::SelectIntrinCall(IntrinsiccallNode &intrinsiccallNode) +void X64CGFunc::SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) { CHECK_FATAL(false, "NIY"); } @@ -235,7 +235,7 @@ Operand *X64CGFunc::SelectCAtomicLoadN(IntrinsicopNode &intrinsicopNode) CHECK_FATAL(false, "NIY"); return nullptr; } -Operand *X64CGFunc::SelectCAtomicExchangeN(IntrinsicopNode &intrinsicopNode) +Operand *X64CGFunc::SelectCAtomicExchangeN(const IntrinsiccallNode &intrinsicopNode) { CHECK_FATAL(false, "NIY"); return nullptr; @@ -306,7 +306,7 @@ Operand *X64CGFunc::SelectIreadfpoff(const BaseNode &parent, IreadFPoffNode &ire CHECK_FATAL(false, "NIY"); return nullptr; } -Operand *X64CGFunc::SelectIntConst(const MIRIntConst &intConst) +Operand *X64CGFunc::SelectIntConst(const MIRIntConst &intConst, const BaseNode &parent) { CHECK_FATAL(false, "NIY"); return nullptr; @@ -965,7 +965,7 @@ MemOperand *X64CGFunc::GetOrCreatSpillMem(regno_t vrNum, uint32 memSize) if (it != reuseSpillLocMem.end()) { MemOperand *memOpnd = it->second->GetOne(); if (memOpnd != nullptr) { - spillRegMemOperands.emplace(std::pair(vrNum, memOpnd)); + spillRegMemOperands.emplace(std::pair(vrNum, memOpnd)); return memOpnd; } } @@ -973,7 +973,7 @@ MemOperand *X64CGFunc::GetOrCreatSpillMem(regno_t vrNum, uint32 memSize) RegOperand &baseOpnd = GetOrCreateStackBaseRegOperand(); int32 offset = GetOrCreatSpillRegLocation(vrNum, memBitSize / kBitsPerByte); MemOperand *memOpnd = &GetOpndBuilder()->CreateMem(baseOpnd, offset, memBitSize); - spillRegMemOperands.emplace(std::pair(vrNum, memOpnd)); + spillRegMemOperands.emplace(std::pair(vrNum, memOpnd)); return memOpnd; } else { return p->second; @@ -990,10 +990,10 @@ void X64OpndDumpVisitor::Visit(maplebe::RegOperand *v) const OpndDesc *regDesc = GetOpndDesc(); LogInfo::MapleLogger() << " ["; if (regDesc->IsRegDef()) { - LogInfo::MapleLogger() << "DEF,"; + LogInfo::MapleLogger() << "DEF "; } if (regDesc->IsRegUse()) { - LogInfo::MapleLogger() << "USE,"; + LogInfo::MapleLogger() << "USE "; } LogInfo::MapleLogger() << "]"; DumpOpndSuffix(); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_emitter.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_emitter.cpp index 7a7de09679be153ccc01cc7565c86ddfb2a76083..006dd1499a47f52d10a97b438246f4851bc7708c 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_emitter.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/x86_64/x64_emitter.cpp @@ -227,7 +227,7 @@ int64 X64Emitter::TransferLabel(Operand *opnd, uint32 funcUniqueId) { LabelOperand *v = static_cast(opnd); int64 labelSymIdx = CalculateLabelSymIdx(funcUniqueId, v->GetLabelIndex()); - assmbler.StoreNameIntoSymMap(labelSymIdx, v->GetParentFunc()); + assmbler.StoreNameIntoSymMap(labelSymIdx, std::string(v->GetParentFunc().c_str())); return labelSymIdx; } diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/litecg/lmir_builder.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/litecg/lmir_builder.cpp index 01784c17fd74067fd5009080dd4162ad4236e6ab..3fc36fcbf202df942c2975f9ebe8e79d22b42c98 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/litecg/lmir_builder.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/litecg/lmir_builder.cpp @@ -176,7 +176,8 @@ bool LMIRBuilder::IsHeapPointerType(Type *mirType) const ArrayType *LMIRBuilder::CreateArrayType(Type *elemType, std::vector &dimSize) { - auto type = GlobalTables::GetTypeTable().GetOrCreateArrayType(*elemType, dimSize.size(), dimSize.data()); + auto type = GlobalTables::GetTypeTable().GetOrCreateArrayType(*elemType, dimSize.size(), + reinterpret_cast(dimSize.data())); return static_cast(type); } diff --git a/ecmascript/compiler/codegen/maple/maple_driver/include/triple.h b/ecmascript/compiler/codegen/maple/maple_driver/include/triple.h index 6f8bc1a4a5e124050fe2c845314ec6800599f80e..7bac8bd907752fbf92b725c25470cb4e0d805106 100644 --- a/ecmascript/compiler/codegen/maple/maple_driver/include/triple.h +++ b/ecmascript/compiler/codegen/maple/maple_driver/include/triple.h @@ -28,7 +28,7 @@ namespace maple { class Triple { public: /* Currently, only aarch64 is supported */ - enum ArchType { UnknownArch, aarch64, aarch64_be, LastArchType }; + enum ArchType { UnknownArch, aarch64, aarch64_be, X64, LastArchType }; /* Currently, only ILP32 and LP64 are supported */ enum EnvironmentType { UnknownEnvironment, GNU, GNUILP32, LastEnvironmentType }; @@ -47,6 +47,11 @@ public: return (GetArch() == ArchType::aarch64_be); } + bool IsAarch64BeOrLe() const + { + return (GetArch() == ArchType::aarch64_be || GetArch() == ArchType::aarch64); + } + std::string Str() const; std::string GetArchName() const; std::string GetEnvironmentName() const; diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/global_tables.h b/ecmascript/compiler/codegen/maple/maple_ir/include/global_tables.h index 0f5062afa9549f4a9073c433edfe0f5e2f63ba4c..20fc90d8c834029eb5e9de6266c051a5acea7c43 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/global_tables.h +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/global_tables.h @@ -481,10 +481,10 @@ public: } void UpdateMIRType(const MIRType &pType, const TyIdx tyIdx); - MIRArrayType *GetOrCreateArrayType(const MIRType &elem, uint8 dim, const uint32 *sizeArray, + MIRArrayType *GetOrCreateArrayType(const MIRType &elem, uint8 dim, const uint64 *sizeArray, const TypeAttrs &attrs = TypeAttrs()); // For one dimention array - MIRArrayType *GetOrCreateArrayType(const MIRType &elem, uint32 size, const TypeAttrs &attrs = TypeAttrs()); + MIRArrayType *GetOrCreateArrayType(const MIRType &elem, uint64 size, const TypeAttrs &attrs = TypeAttrs()); MIRType *GetOrCreateFarrayType(const MIRType &elem); MIRType *GetOrCreateJarrayType(const MIRType &elem); MIRType *GetOrCreateFunctionType(const TyIdx &, const std::vector &, const std::vector &, diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsic_c.def b/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsic_c.def index 275420766913b2786884084fca3ca5016815c4c4..cf6db81a4b0cc2af25d1dd1406315b89514ba9b4 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsic_c.def +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/intrinsic_c.def @@ -257,6 +257,8 @@ DEF_MIR_INTRINSIC(C__builtin_extract_return_addr,\ "__builtin_extract_return_addr", INTRNISPURE, kArgTyPtr, kArgTyPtr) DEF_MIR_INTRINSIC(C___builtin_expect,\ "__builtin_expect", INTRNISPURE, kArgTyI32, kArgTyI32, kArgTyI32) +DEF_MIR_INTRINSIC(C___builtin_division_exception,\ + "__builtin_division_exception", INTRNNOSIDEEFFECT | INTRNISPURE, kArgTyVoid, kArgTyI64) // atomic DEF_MIR_INTRINSIC(C___atomic_load_n,\ diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_scope.h b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_scope.h index 300bc12ff0f5e041b61371a9777f3044a6ee9ef2..1317e56736345a40423dc4ffba2dde3b3f5aa273 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_scope.h +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_scope.h @@ -67,7 +67,6 @@ public: void SetAliasVarMap(GStrIdx idx, const MIRAliasVars &vars) { - DEBUG_ASSERT(aliasVarMap.find(idx) == aliasVarMap.end(), "alias already exist"); aliasVarMap[idx] = vars; } diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_symbol.h b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_symbol.h index 0ab6daceb483bee6eedd223bc7a5261f601abee7..92b7cbe334b42d78081d92facc7786036da3166a 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_symbol.h +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_symbol.h @@ -19,6 +19,7 @@ #include "mir_const.h" #include "mir_preg.h" #include "src_position.h" +#include "triple.h" constexpr int kScopeLocal = 2; // the default scope level for function variables constexpr int kScopeGlobal = 1; // the scope level for global variables @@ -574,6 +575,36 @@ public: } } + uint8 GetSymbolAlign(bool isArm64ilp32) const + { + uint8 align = GetAttrs().GetAlignValue(); + if (align == 0) { + if (GetType()->GetKind() == kTypeStruct || GetType()->GetKind() == kTypeClass || + GetType()->GetKind() == kTypeArray || GetType()->GetKind() == kTypeUnion) { + // when x64 does not driver, there is no triple init, this is a temporary plan + if (Triple::GetTriple().GetArch() == Triple::ArchType::X64 || + Triple::GetTriple().GetArch() == Triple::ArchType::UnknownArch) { + return align; + } + uint8 alignMin = 0; + if (GetType()->GetAlign() > 0) { + alignMin = static_cast(log2(GetType()->GetAlign())); + } + align = std::max(3, alignMin); // 3: alignment in bytes of uint8 + } else { + align = static_cast(GetType()->GetAlign()); + if (Triple::GetTriple().IsAarch64BeOrLe()) { + if (isArm64ilp32 && GetType()->GetPrimType() == PTY_a32) { + align = 3; // 3: alignment in bytes of uint8 + } else { + align = static_cast(log2(align)); + } + } + } + } + return align; + } + // Please keep order of the fields, avoid paddings. private: TyIdx tyIdx {0}; diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_type.h b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_type.h index 1a62520915be4b8839756f28d4676e891eaa9cb3..c3c788856d6505265a0c0063bf67a1bb08007f4c 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_type.h +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_type.h @@ -1111,7 +1111,7 @@ public: MIRArrayType() : MIRType(kTypeArray, PTY_agg) {} explicit MIRArrayType(GStrIdx strIdx) : MIRType(kTypeArray, PTY_agg, strIdx) {} - MIRArrayType(TyIdx eTyIdx, const std::vector &sizeArray) + MIRArrayType(TyIdx eTyIdx, const std::vector &sizeArray) : MIRType(kTypeArray, PTY_agg), eTyIdx(eTyIdx), dim(sizeArray.size()) { for (size_t i = 0; i < kMaxArrayDim; ++i) { @@ -1132,12 +1132,12 @@ public: eTyIdx = idx; } - uint32 GetSizeArrayItem(uint32 n) const + uint64 GetSizeArrayItem(uint32 n) const { CHECK_FATAL((n >= 0 && n < kMaxArrayDim), "out of bound of array!"); return sizeArray[n]; } - void SetSizeArrayItem(uint32 idx, uint32 value) + void SetSizeArrayItem(uint32 idx, uint64 value) { CHECK_FATAL((idx >= 0 && idx < kMaxArrayDim), "out of bound of array!"); sizeArray[idx] = value; @@ -1221,7 +1221,7 @@ public: private: TyIdx eTyIdx {0}; uint16 dim = 0; - std::array sizeArray {{0}}; + std::array sizeArray {{0}}; TypeAttrs typeAttrs; mutable uint32 fieldsNum = kInvalidFieldNum; mutable size_t size = kInvalidSize; diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/types_def.h b/ecmascript/compiler/codegen/maple/maple_ir/include/types_def.h index 7658944350687e95ec388153382bb3a432b93e17..d87330e35de1309ab449d1af427fadb9273c6a00 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/types_def.h +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/types_def.h @@ -34,6 +34,8 @@ using uint8 = std::uint8_t; using uint16 = std::uint16_t; using uint32 = std::uint32_t; using uint64 = std::uint64_t; +typedef unsigned int uint; + class StIdx { // scope nesting level + symbol table index public: union un { diff --git a/ecmascript/compiler/codegen/maple/maple_ir/src/bin_func_import.cpp b/ecmascript/compiler/codegen/maple/maple_ir/src/bin_func_import.cpp index 89e89eec95e0ed829e4b6eb1593305003425d022..64b1dc9bf1f32819061ec2d775b116d3880eeb03 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/src/bin_func_import.cpp +++ b/ecmascript/compiler/codegen/maple/maple_ir/src/bin_func_import.cpp @@ -47,7 +47,7 @@ void BinaryMplImport::ImportFuncIdInfo(MIRFunction *func) func->SetPuidxOrigin(static_cast(ReadNum())); ImportInfoVector(func->GetInfoVector(), func->InfoIsString()); if (mod.GetFlavor() == kFlavorLmbc) { - func->SetFrameSize(static_cast(ReadNum())); + func->SetFrameSize(static_cast(ReadNum())); } } diff --git a/ecmascript/compiler/codegen/maple/maple_ir/src/global_tables.cpp b/ecmascript/compiler/codegen/maple/maple_ir/src/global_tables.cpp index be9278afbf8bda9c6d9d33c1a32659f68914818b..1f519801eddc10c9ebe5c565f2d0102ca961217e 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/src/global_tables.cpp +++ b/ecmascript/compiler/codegen/maple/maple_ir/src/global_tables.cpp @@ -221,10 +221,10 @@ MIRType *TypeTable::GetPointedTypeIfApplicable(MIRType &type) return const_cast(const_cast(this)->GetPointedTypeIfApplicable(type)); } -MIRArrayType *TypeTable::GetOrCreateArrayType(const MIRType &elem, uint8 dim, const uint32 *sizeArray, +MIRArrayType *TypeTable::GetOrCreateArrayType(const MIRType &elem, uint8 dim, const uint64 *sizeArray, const TypeAttrs &attrs) { - std::vector sizeVector; + std::vector sizeVector; for (size_t i = 0; i < dim; ++i) { sizeVector.push_back(sizeArray != nullptr ? sizeArray[i] : 0); } @@ -235,7 +235,7 @@ MIRArrayType *TypeTable::GetOrCreateArrayType(const MIRType &elem, uint8 dim, co } // For one dimension array -MIRArrayType *TypeTable::GetOrCreateArrayType(const MIRType &elem, uint32 size, const TypeAttrs &attrs) +MIRArrayType *TypeTable::GetOrCreateArrayType(const MIRType &elem, uint64 size, const TypeAttrs &attrs) { return GetOrCreateArrayType(elem, 1, &size, attrs); } diff --git a/ecmascript/compiler/codegen/maple/maple_ir/src/mir_builder.cpp b/ecmascript/compiler/codegen/maple/maple_ir/src/mir_builder.cpp index a3a46d833d3d646c8a0d228359ee090b980c2eac..27377ae9d793e718335d2f13be17a7002bba98ab 100755 --- a/ecmascript/compiler/codegen/maple/maple_ir/src/mir_builder.cpp +++ b/ecmascript/compiler/codegen/maple/maple_ir/src/mir_builder.cpp @@ -508,7 +508,7 @@ MIRSymbol *MIRBuilder::CreateConstStringSymbol(const std::string &symbolName, co { auto elemPrimType = PTY_u8; MIRType *type = GlobalTables::GetTypeTable().GetPrimType(elemPrimType); - uint32 sizeIn = static_cast(content.length()); + uint64 sizeIn = static_cast(content.length()); MIRType *arrayTypeWithSize = GlobalTables::GetTypeTable().GetOrCreateArrayType( *GlobalTables::GetTypeTable().GetPrimType(elemPrimType), 1, &sizeIn); diff --git a/ecmascript/compiler/codegen/maple/maple_ir/src/parser.cpp b/ecmascript/compiler/codegen/maple/maple_ir/src/parser.cpp index 909bc0bb21ae8c2eada6bcf22bfadea560b0d7b9..5a1fbd03edab08a5eb7b7f1155784ab88c50fcbd 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/src/parser.cpp +++ b/ecmascript/compiler/codegen/maple/maple_ir/src/parser.cpp @@ -295,7 +295,7 @@ bool MIRParser::ParseArrayType(TyIdx &arrayTyIdx) Error("expect [ for array type but get "); return false; } - std::vector vec; + std::vector vec; while (tokenKind == TK_lbrack) { tokenKind = lexer.NextToken(); if (tokenKind == TK_rbrack && vec.empty()) { @@ -2270,7 +2270,7 @@ bool MIRParser::ParseInitValue(MIRConstPtr &theConst, TyIdx tyIdx, bool allowEmp if (arrayType.GetDim() == 1) { elemTyIdx = elemType->GetTypeIndex(); } else { - std::vector sizeSubArray; + std::vector sizeSubArray; for (uint16 i = 1; i < arrayType.GetDim(); ++i) { sizeSubArray.push_back(arrayType.GetSizeArrayItem(i)); } diff --git a/ecmascript/compiler/codegen/maple/maple_me/include/me_ir.h b/ecmascript/compiler/codegen/maple/maple_me/include/me_ir.h index 597038081d89e5a23c008db288dca0a7e657e6c3..ba8a6daa600ded66df5a81d56ba55f1cc693dc22 100644 --- a/ecmascript/compiler/codegen/maple/maple_me/include/me_ir.h +++ b/ecmascript/compiler/codegen/maple/maple_me/include/me_ir.h @@ -2497,6 +2497,11 @@ public: CallMeStmt(MapleAllocator *alloc, Opcode op) : NaryMeStmt(alloc, op), MuChiMePart(alloc), AssignedPart(alloc) {} + CallMeStmt(MapleAllocator *alloc, Opcode op, PUIdx idx) + : NaryMeStmt(alloc, op), MuChiMePart(alloc), AssignedPart(alloc), puIdx(idx) + { + } + CallMeStmt(MapleAllocator *alloc, const NaryMeStmt *cstmt, PUIdx idx) : NaryMeStmt(alloc, cstmt), MuChiMePart(alloc), AssignedPart(alloc), puIdx(idx) { diff --git a/ecmascript/compiler/codegen/maple/maple_me/include/orig_symbol.h b/ecmascript/compiler/codegen/maple/maple_me/include/orig_symbol.h index 0e89409da55521082b99a1287a08000780e8d705..f837f48c5372cb7bb79d6342d660c6decf1e60f9 100644 --- a/ecmascript/compiler/codegen/maple/maple_me/include/orig_symbol.h +++ b/ecmascript/compiler/codegen/maple/maple_me/include/orig_symbol.h @@ -92,6 +92,13 @@ public: return true; } if (fieldID != 0) { + auto type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(symOrPreg.mirSt->GetTyIdx()); + if (type->IsMIRArrayType()) { + type = static_cast(type)->GetElemType(); + } + if (!type->IsMIRStructType()) { + return false; + } MIRStructType *structType = static_cast( GlobalTables::GetTypeTable().GetTypeFromTyIdx(symOrPreg.mirSt->GetTyIdx())); FieldAttrs fattrs = structType->GetFieldAttrs(fieldID);