diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td index 06c628d5000f..9599a572141e 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -389,12 +389,14 @@ def simm10Scaled : Operand { let ParserMatchClass = SImm10s8Operand; let DecoderMethod = "DecodeSImm<10>"; let PrintMethod = "printImmScale<8>"; + let OperandType = "OPERAND_IMMEDIATE"; } def simm9s16 : Operand { let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>; let DecoderMethod = "DecodeSImm<9>"; let PrintMethod = "printImmScale<16>"; + let OperandType = "OPERAND_IMMEDIATE"; } // uimm6 predicate - True if the immediate is in the range [0, 63]. @@ -405,18 +407,22 @@ def UImm6Operand : AsmOperandClass { def uimm6 : Operand, ImmLeaf= 0 && Imm < 64; }]> { let ParserMatchClass = UImm6Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm16 : Operand, ImmLeaf= 0 && Imm < 65536;}]>{ let ParserMatchClass = AsmImmRange<0, 65535>; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm6_64b : Operand, ImmLeaf= 0 && Imm < 64; }]> { let ParserMatchClass = UImm6Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm6_32b : Operand, ImmLeaf= 0 && Imm < 64; }]> { let ParserMatchClass = UImm6Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def CmpBranchUImm6Operand_32b @@ -453,24 +459,29 @@ def UImm6Minus1Operand : AsmOperandClass { def uimm6p1_32b : Operand { let ParserMatchClass = UImm6Plus1Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm6p1_64b : Operand { let ParserMatchClass = UImm6Plus1Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm6m1_32b : Operand { let ParserMatchClass = UImm6Minus1Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm6m1_64b : Operand { let ParserMatchClass = UImm6Minus1Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def SImm9Operand : SImmOperand<9>; def simm9 : Operand, ImmLeaf= -256 && Imm < 256; }]> { let ParserMatchClass = SImm9Operand; let DecoderMethod = "DecodeSImm<9>"; + let OperandType = "OPERAND_IMMEDIATE"; } // imm0_255 predicate - True if the immediate is in the range [0,255]. @@ -478,48 +489,57 @@ def Imm0_255Operand : AsmImmRange<0,255>; def uimm8_32b : Operand, ImmLeaf= 0 && Imm < 256; }]> { let ParserMatchClass = Imm0_255Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm8_64b : Operand, ImmLeaf= 0 && Imm < 256; }]> { let ParserMatchClass = Imm0_255Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def SImm8Operand : SImmOperand<8>; def simm8_32b : Operand, ImmLeaf= -128 && Imm < 128; }]> { let ParserMatchClass = SImm8Operand; let DecoderMethod = "DecodeSImm<8>"; + let OperandType = "OPERAND_IMMEDIATE"; } def simm8_64b : Operand, ImmLeaf= -128 && Imm < 128; }]> { let ParserMatchClass = SImm8Operand; let DecoderMethod = "DecodeSImm<8>"; + let OperandType = "OPERAND_IMMEDIATE"; } def SImm6Operand : SImmOperand<6>; def simm6_32b : Operand, ImmLeaf= -32 && Imm < 32; }]> { let ParserMatchClass = SImm6Operand; let DecoderMethod = "DecodeSImm<6>"; + let OperandType = "OPERAND_IMMEDIATE"; } def SImm5Operand : SImmOperand<5>; def simm5_64b : Operand, ImmLeaf= -16 && Imm < 16; }]> { let ParserMatchClass = SImm5Operand; let DecoderMethod = "DecodeSImm<5>"; + let OperandType = "OPERAND_IMMEDIATE"; } def simm5_32b : Operand, ImmLeaf= -16 && Imm < 16; }]> { let ParserMatchClass = SImm5Operand; let DecoderMethod = "DecodeSImm<5>"; + let OperandType = "OPERAND_IMMEDIATE"; } def simm5_8b : Operand, ImmLeaf= -16 && (int8_t)Imm < 16; }]> { let ParserMatchClass = SImm5Operand; let DecoderMethod = "DecodeSImm<5>"; let PrintMethod = "printSImm<8>"; + let OperandType = "OPERAND_IMMEDIATE"; } def simm5_16b : Operand, ImmLeaf= -16 && (int16_t)Imm < 16; }]> { let ParserMatchClass = SImm5Operand; let DecoderMethod = "DecodeSImm<5>"; let PrintMethod = "printSImm<16>"; + let OperandType = "OPERAND_IMMEDIATE"; } // simm7sN predicate - True if the immediate is a multiple of N in the range @@ -532,16 +552,19 @@ def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>; def simm7s4 : Operand { let ParserMatchClass = SImm7s4Operand; let PrintMethod = "printImmScale<4>"; + let OperandType = "OPERAND_IMMEDIATE"; } def simm7s8 : Operand { let ParserMatchClass = SImm7s8Operand; let PrintMethod = "printImmScale<8>"; + let OperandType = "OPERAND_IMMEDIATE"; } def simm7s16 : Operand { let ParserMatchClass = SImm7s16Operand; let PrintMethod = "printImmScale<16>"; + let OperandType = "OPERAND_IMMEDIATE"; } def am_sve_fi : ComplexPattern; @@ -591,18 +614,21 @@ def uimm5s2 : Operand, ImmLeaf { let ParserMatchClass = UImm5s2Operand; let PrintMethod = "printImmScale<2>"; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm5s4 : Operand, ImmLeaf= 0 && Imm < (32*4) && ((Imm % 4) == 0); }], UImmS4XForm> { let ParserMatchClass = UImm5s4Operand; let PrintMethod = "printImmScale<4>"; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm5s8 : Operand, ImmLeaf= 0 && Imm < (32*8) && ((Imm % 8) == 0); }], UImmS8XForm> { let ParserMatchClass = UImm5s8Operand; let PrintMethod = "printImmScale<8>"; + let OperandType = "OPERAND_IMMEDIATE"; } // tuimm5sN predicate - similar to uimm5sN, but use TImmLeaf (TargetConstant) @@ -612,18 +638,21 @@ def tuimm5s2 : Operand, TImmLeaf { let ParserMatchClass = UImm5s2Operand; let PrintMethod = "printImmScale<2>"; + let OperandType = "OPERAND_IMMEDIATE"; } def tuimm5s4 : Operand, TImmLeaf= 0 && Imm < (32*4) && ((Imm % 4) == 0); }], UImmS4XForm> { let ParserMatchClass = UImm5s4Operand; let PrintMethod = "printImmScale<4>"; + let OperandType = "OPERAND_IMMEDIATE"; } def tuimm5s8 : Operand, TImmLeaf= 0 && Imm < (32*8) && ((Imm % 8) == 0); }], UImmS8XForm> { let ParserMatchClass = UImm5s8Operand; let PrintMethod = "printImmScale<8>"; + let OperandType = "OPERAND_IMMEDIATE"; } // uimm6sN predicate - True if the immediate is a multiple of N in the range @@ -636,26 +665,31 @@ def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>; def uimm6s1 : Operand, ImmLeaf= 0 && Imm < 64; }]> { let ParserMatchClass = UImm6s1Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm6s2 : Operand, ImmLeaf= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> { let PrintMethod = "printImmScale<2>"; let ParserMatchClass = UImm6s2Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm6s4 : Operand, ImmLeaf= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> { let PrintMethod = "printImmScale<4>"; let ParserMatchClass = UImm6s4Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm6s8 : Operand, ImmLeaf= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> { let PrintMethod = "printImmScale<8>"; let ParserMatchClass = UImm6s8Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm6s16 : Operand, ImmLeaf= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> { let PrintMethod = "printImmScale<16>"; let ParserMatchClass = UImm6s16Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def SImmS2XForm : SDNodeXForm; def simm6s1 : Operand, ImmLeaf= -32 && Imm < 32; }]> { let ParserMatchClass = SImm6s1Operand; let DecoderMethod = "DecodeSImm<6>"; + let OperandType = "OPERAND_IMMEDIATE"; } // simm4sN predicate - True if the immediate is a multiple of N in the range @@ -695,6 +730,7 @@ def simm4s1 : Operand, ImmLeaf=-8 && Imm <= 7; }]> { let ParserMatchClass = SImm4s1Operand; let DecoderMethod = "DecodeSImm<4>"; + let OperandType = "OPERAND_IMMEDIATE"; } def simm4s2 : Operand, ImmLeaf, ImmLeaf, ImmLeaf, ImmLeaf, ImmLeaf, ImmLeaf, ImmLeaf=-128 && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> { let PrintMethod = "printImmScale<16>"; let ParserMatchClass = SImm4s16Operand; let DecoderMethod = "DecodeSImm<4>"; + let OperandType = "OPERAND_IMMEDIATE"; } def simm4s32 : Operand, ImmLeaf=-256 && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> { let PrintMethod = "printImmScale<32>"; let ParserMatchClass = SImm4s32Operand; let DecoderMethod = "DecodeSImm<4>"; + let OperandType = "OPERAND_IMMEDIATE"; } def Imm1_8Operand : AsmImmRange<1, 8>; @@ -757,6 +798,7 @@ def MovWSymbolG3AsmOperand : AsmOperandClass { def movw_symbol_g3 : Operand { let ParserMatchClass = MovWSymbolG3AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; } def MovWSymbolG2AsmOperand : AsmOperandClass { @@ -766,6 +808,7 @@ def MovWSymbolG2AsmOperand : AsmOperandClass { def movw_symbol_g2 : Operand { let ParserMatchClass = MovWSymbolG2AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; } def MovWSymbolG1AsmOperand : AsmOperandClass { @@ -775,6 +818,7 @@ def MovWSymbolG1AsmOperand : AsmOperandClass { def movw_symbol_g1 : Operand { let ParserMatchClass = MovWSymbolG1AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; } def MovWSymbolG0AsmOperand : AsmOperandClass { @@ -784,6 +828,7 @@ def MovWSymbolG0AsmOperand : AsmOperandClass { def movw_symbol_g0 : Operand { let ParserMatchClass = MovWSymbolG0AsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; } class fixedpoint_i32 @@ -792,6 +837,7 @@ class fixedpoint_i32 let EncoderMethod = "getFixedPointScaleOpValue"; let DecoderMethod = "DecodeFixedPointScaleImm32"; let ParserMatchClass = Imm1_32Operand; + let OperandType = "OPERAND_IMMEDIATE"; } class fixedpoint_i64 @@ -800,6 +846,7 @@ class fixedpoint_i64 let EncoderMethod = "getFixedPointScaleOpValue"; let DecoderMethod = "DecodeFixedPointScaleImm64"; let ParserMatchClass = Imm1_64Operand; + let OperandType = "OPERAND_IMMEDIATE"; } def fixedpoint_f16_i32 : fixedpoint_i32; @@ -815,6 +862,7 @@ class fixedpoint_recip_i32 ComplexPattern", [fpimm, ld]> { let EncoderMethod = "getFixedPointScaleOpValue"; let DecoderMethod = "DecodeFixedPointScaleImm32"; + let OperandType = "OPERAND_IMMEDIATE"; } class fixedpoint_recip_i64 @@ -822,6 +870,7 @@ class fixedpoint_recip_i64 ComplexPattern", [fpimm, ld]> { let EncoderMethod = "getFixedPointScaleOpValue"; let DecoderMethod = "DecodeFixedPointScaleImm64"; + let OperandType = "OPERAND_IMMEDIATE"; } def fixedpoint_recip_f16_i32 : fixedpoint_recip_i32; @@ -838,6 +887,7 @@ def vecshiftR8 : Operand, TImmLeaf, TImmLeaf 0) && (((uint32_t)Imm) < 17); @@ -845,6 +895,7 @@ def vecshiftR16 : Operand, TImmLeaf, TImmLeaf 0) && (((uint32_t)Imm) < 9); @@ -852,6 +903,7 @@ def vecshiftR16Narrow : Operand, TImmLeaf, TImmLeaf 0) && (((uint32_t)Imm) < 33); @@ -859,6 +911,7 @@ def vecshiftR32 : Operand, TImmLeaf, TImmLeaf 0) && (((uint32_t)Imm) < 17); @@ -866,6 +919,7 @@ def vecshiftR32Narrow : Operand, TImmLeaf, TImmLeaf 0) && (((uint32_t)Imm) < 65); @@ -873,6 +927,7 @@ def vecshiftR64 : Operand, TImmLeaf, TImmLeaf 0) && (((uint32_t)Imm) < 33); @@ -880,6 +935,7 @@ def vecshiftR64Narrow : Operand, TImmLeaf; @@ -899,6 +955,7 @@ def vecshiftL8 : Operand, TImmLeaf, TImmLeaf, TImmLeaf, TImmLeaf, TImmLeaf, TImmLeaf, TImmLeaf ComplexPattern { let PrintMethod = "printShiftedRegister"; let MIOperandInfo = (ops regclass, !cast("arith_shift" # width)); + let OperandType = "OPERAND_SHIFTED_REGISTER"; + let OperandNamespace = "AArch64"; } def arith_shifted_reg32 : arith_shifted_reg; @@ -1239,6 +1301,7 @@ class logical_shift : Operand { let PrintMethod = "printShifter"; let ParserMatchClass = !cast( "LogicalShifterOperand" # width); + let OperandType = "OPERAND_IMMEDIATE"; } def logical_shift32 : logical_shift<32>; @@ -1249,6 +1312,8 @@ class logical_shifted_reg ComplexPattern { let PrintMethod = "printShiftedRegister"; let MIOperandInfo = (ops regclass, shiftop); + let OperandType = "OPERAND_SHIFTED_REGISTER"; + let OperandNamespace = "AArch64"; } def logical_shifted_reg32 : logical_shifted_reg; @@ -1269,6 +1334,8 @@ def logical_vec_shift : Operand { let PrintMethod = "printShifter"; let EncoderMethod = "getVecShifterOpValue"; let ParserMatchClass = LogicalVecShifterOperand; + let OperandType = "OPERAND_SHIFTED_IMMEDIATE"; + let OperandNamespace = "AArch64"; } // A logical vector half-word shifter operand: @@ -1278,6 +1345,8 @@ def logical_vec_hw_shift : Operand { let PrintMethod = "printShifter"; let EncoderMethod = "getVecShifterOpValue"; let ParserMatchClass = LogicalVecHalfWordShifterOperand; + let OperandType = "OPERAND_SHIFTED_IMMEDIATE"; + let OperandNamespace = "AArch64"; } // A vector move shifter operand: @@ -1312,6 +1381,8 @@ class addsub_shifted_imm let EncoderMethod = "getAddSubImmOpValue"; let ParserMatchClass = AddSubImmOperand; let MIOperandInfo = (ops i32imm, i32imm); + let OperandType = "OPERAND_SHIFTED_IMMEDIATE"; + let OperandNamespace = "AArch64"; } class addsub_shifted_imm_neg @@ -1319,6 +1390,8 @@ class addsub_shifted_imm_neg let EncoderMethod = "getAddSubImmOpValue"; let ParserMatchClass = AddSubImmNegOperand; let MIOperandInfo = (ops i32imm, i32imm); + let OperandType = "OPERAND_SHIFTED_IMMEDIATE"; + let OperandNamespace = "AArch64"; } def addsub_shifted_imm32 : addsub_shifted_imm; @@ -1340,6 +1413,8 @@ class neg_addsub_shifted_imm let EncoderMethod = "getAddSubImmOpValue"; let ParserMatchClass = AddSubImmOperand; let MIOperandInfo = (ops i32imm, i32imm); + let OperandType = "OPERAND_SHIFTED_IMMEDIATE"; + let OperandNamespace = "AArch64"; } def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm; @@ -1359,28 +1434,35 @@ def gi_neg_addsub_shifted_imm64 : def arith_extend : Operand { let PrintMethod = "printArithExtend"; let ParserMatchClass = ExtendOperand; + let OperandType = "OPERAND_IMMEDIATE"; } def arith_extend64 : Operand { let PrintMethod = "printArithExtend"; let ParserMatchClass = ExtendOperand64; + let OperandType = "OPERAND_IMMEDIATE"; } // 'extend' that's a lsl of a 64-bit register. def arith_extendlsl64 : Operand { let PrintMethod = "printArithExtend"; let ParserMatchClass = ExtendOperandLSL64; + let OperandType = "OPERAND_IMMEDIATE"; } class arith_extended_reg32 : Operand, ComplexPattern { let PrintMethod = "printExtendedRegister"; let MIOperandInfo = (ops GPR32, arith_extend); + let OperandType = "OPERAND_SHIFTED_REGISTER"; + let OperandNamespace = "AArch64"; } class arith_extended_reg32to64 : Operand, ComplexPattern { let PrintMethod = "printExtendedRegister"; let MIOperandInfo = (ops GPR32, arith_extend64); + let OperandType = "OPERAND_SHIFTED_REGISTER"; + let OperandNamespace = "AArch64"; } def arith_extended_reg32_i32 : arith_extended_reg32; @@ -1462,6 +1544,7 @@ def fpimm64 : Operand, def fpimm8 : Operand { let ParserMatchClass = FPImmOperand; let PrintMethod = "printFPImmOperand"; + let OperandType = "OPERAND_IMMEDIATE"; } def fpimm0 : FPImmLeaf; } +let OperandType = "OPERAND_IMMEDIATE" in { defm VectorIndex1 : VectorIndex; defm VectorIndexB : VectorIndex; defm VectorIndexD32b : VectorIndex; +} def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">; def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">; @@ -1555,6 +1640,7 @@ def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">; def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">; def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">; +let OperandType = "OPERAND_IMMEDIATE" in { defm sve_elm_idx_extdup_b : VectorIndex; @@ -1570,6 +1656,7 @@ defm sve_elm_idx_extdup_d defm sve_elm_idx_extdup_q : VectorIndex; +} def sme_elm_idx0_0 : Operand, TImmLeaf, TImmLeaf { let ParserMatchClass = Imm0_1Operand; let PrintMethod = "printMatrixIndex"; + let OperandType = "OPERAND_IMMEDIATE"; } def sme_elm_idx0_3 : Operand, TImmLeaf { let ParserMatchClass = Imm0_3Operand; let PrintMethod = "printMatrixIndex"; + let OperandType = "OPERAND_IMMEDIATE"; } def sme_elm_idx0_7 : Operand, TImmLeaf { let ParserMatchClass = Imm0_7Operand; let PrintMethod = "printMatrixIndex"; + let OperandType = "OPERAND_IMMEDIATE"; } def sme_elm_idx0_15 : Operand, TImmLeaf { let ParserMatchClass = Imm0_15Operand; let PrintMethod = "printMatrixIndex"; + let OperandType = "OPERAND_IMMEDIATE"; } // SME2 vector select offset operands @@ -1615,6 +1706,7 @@ def uimm3s8 : Operand, ImmLeaf= 0 && Imm <= 56 && ((Imm % 8) == 0); }], UImmS8XForm> { let PrintMethod = "printMatrixIndex<8>"; let ParserMatchClass = UImm3s8Operand; + let OperandType = "OPERAND_IMMEDIATE"; } class UImmScaledMemoryIndexedRange : AsmOperandClass { @@ -1658,30 +1750,35 @@ def uimm1s2range : Operand, ImmLeaf= 0 && Imm <= 2 && ((Imm % 2) == 0); }], UImmS2XForm> { let PrintMethod = "printImmRangeScale<2, 1>"; let ParserMatchClass = UImm1s2RangeOperand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm1s4range : Operand, ImmLeaf= 0 && Imm <= 4 && ((Imm % 4) == 0); }], UImmS4XForm> { let PrintMethod = "printImmRangeScale<4, 3>"; let ParserMatchClass = UImm1s4RangeOperand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm2s2range : Operand, ImmLeaf= 0 && Imm <= 6 && ((Imm % 2) == 0); }], UImmS2XForm> { let PrintMethod = "printImmRangeScale<2, 1>"; let ParserMatchClass = UImm2s2RangeOperand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm2s4range : Operand, ImmLeaf= 0 && Imm <= 12 && ((Imm % 4) == 0); }], UImmS4XForm> { let PrintMethod = "printImmRangeScale<4, 3>"; let ParserMatchClass = UImm2s4RangeOperand; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm3s2range : Operand, ImmLeaf= 0 && Imm <= 14 && ((Imm % 2) == 0); }], UImmS2XForm> { let PrintMethod = "printImmRangeScale<2, 1>"; let ParserMatchClass = UImm3s2RangeOperand; + let OperandType = "OPERAND_IMMEDIATE"; } @@ -1700,6 +1797,7 @@ def simdimmtype10 : Operand, }]>> { let ParserMatchClass = SIMDImmType10Operand; let PrintMethod = "printSIMDType10Operand"; + let OperandType = "OPERAND_IMMEDIATE"; } @@ -1769,6 +1867,7 @@ def PHintInstOperand : AsmOperandClass { def phint_op : Operand { let ParserMatchClass = PHintInstOperand; let PrintMethod = "printPHintOp"; + let OperandType = "OPERAND_IMMEDIATE"; } class STSHHI @@ -1789,6 +1888,7 @@ def BarrierAsmOperand : AsmOperandClass { def barrier_op : Operand { let PrintMethod = "printBarrierOption"; let ParserMatchClass = BarrierAsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; } def BarriernXSAsmOperand : AsmOperandClass { let Name = "BarriernXS"; @@ -1797,6 +1897,7 @@ def BarriernXSAsmOperand : AsmOperandClass { def barrier_nxs_op : Operand { let PrintMethod = "printBarriernXSOption"; let ParserMatchClass = BarriernXSAsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; } class CRmSystemI opc, string asm, list pattern = []> @@ -1831,6 +1932,7 @@ def mrs_sysreg_op : Operand { let ParserMatchClass = MRSSystemRegisterOperand; let DecoderMethod = "DecodeMRSSystemRegister"; let PrintMethod = "printMRSSystemRegister"; + let OperandType = "OPERAND_IMMEDIATE"; } def MSRSystemRegisterOperand : AsmOperandClass { @@ -1842,6 +1944,7 @@ def msr_sysreg_op : Operand { let ParserMatchClass = MSRSystemRegisterOperand; let DecoderMethod = "DecodeMSRSystemRegister"; let PrintMethod = "printMSRSystemRegister"; + let OperandType = "OPERAND_IMMEDIATE"; } def PSBHintOperand : AsmOperandClass { @@ -1858,6 +1961,7 @@ def psbhint_op : Operand { return false; return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr; }]; + let OperandType = "OPERAND_IMMEDIATE"; } def BTIHintOperand : AsmOperandClass { @@ -1873,6 +1977,7 @@ def btihint_op : Operand { return false; return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr; }]; + let OperandType = "OPERAND_IMMEDIATE"; } def CMHPriorityHintOperand : AsmOperandClass { @@ -1888,6 +1993,7 @@ def CMHPriorityHint_op : Operand { return false; return AArch64CMHPriorityHint::lookupCMHPriorityHintByEncoding(MCOp.getImm()) != nullptr; }]; + let OperandType = "OPERAND_IMMEDIATE"; } def TIndexHintOperand : AsmOperandClass { @@ -1939,6 +2045,7 @@ def pstatefield4_op : Operand { return false; return AArch64SVCR::lookupPStateImm0_15ByEncoding(MCOp.getImm()) != nullptr; }]; + let OperandType = "OPERAND_IMMEDIATE"; } // Instructions to modify PSTATE, no input reg @@ -1979,6 +2086,7 @@ def pstatefield1_op : Operand { return false; return AArch64SVCR::lookupPStateImm0_1ByEncoding(MCOp.getImm()) != nullptr; }]; + let OperandType = "OPERAND_IMMEDIATE"; } class MSRpstateImm0_1 @@ -2009,6 +2117,7 @@ def SysCRAsmOperand : AsmOperandClass { def sys_cr_op : Operand { let PrintMethod = "printSysCROperand"; let ParserMatchClass = SysCRAsmOperand; + let OperandType = "OPERAND_IMMEDIATE"; } class SystemXtI @@ -2053,6 +2162,7 @@ def rprfop : Operand, TImmLeaf { let PrintMethod = "printRPRFMOperand"; let ParserMatchClass = RangePrefetchOperand; + let OperandType = "OPERAND_IMMEDIATE"; } // Branch (register) instructions: @@ -2180,6 +2290,7 @@ multiclass AuthLoad { def ccode : Operand { let PrintMethod = "printCondCode"; let ParserMatchClass = CondCode; + let OperandType = "OPERAND_IMMEDIATE"; } def inv_ccode : Operand { // AL and NV are invalid in the aliases which use inv_ccode @@ -2190,6 +2301,7 @@ def inv_ccode : Operand { MCOp.getImm() != AArch64CC::AL && MCOp.getImm() != AArch64CC::NV; }]; + let OperandType = "OPERAND_IMMEDIATE"; } // Conditional branch target. 19-bit immediate. The low two bits of the target @@ -2286,6 +2398,7 @@ class tbz_imm0_31 : Operand, ImmLeaf { let ParserMatchClass = matcher; + let OperandType = "OPERAND_IMMEDIATE"; } def tbz_imm0_31_diag : tbz_imm0_31; @@ -2295,6 +2408,7 @@ def tbz_imm32_63 : Operand, ImmLeaf 31) && (((uint32_t)Imm) < 64); }]> { let ParserMatchClass = TBZImm32_63Operand; + let OperandType = "OPERAND_IMMEDIATE"; } class BaseTestBranch { let ParserMatchClass = AsmImmRange<0, 65535>; let EncoderMethod = "getMoveWideImmOpValue"; let PrintMethod = "printImm"; + let OperandType = "OPERAND_IMMEDIATE"; } def movimm32_shift : Operand { let PrintMethod = "printShifter"; let ParserMatchClass = MovImm32ShifterOperand; + let OperandType = "OPERAND_IMMEDIATE"; } def movimm64_shift : Operand { let PrintMethod = "printShifter"; let ParserMatchClass = MovImm64ShifterOperand; + let OperandType = "OPERAND_IMMEDIATE"; } let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in @@ -3633,9 +3750,11 @@ multiclass CondSelectOp op2, string asm, PatFrag frag> { //--- def maski8_or_more : Operand, ImmLeaf { + let OperandType = "OPERAND_IMMEDIATE"; } def maski16_or_more : Operand, ImmLeaf { + let OperandType = "OPERAND_IMMEDIATE"; } @@ -3693,6 +3812,7 @@ class uimm12_scaled : Operand { let EncoderMethod = "getLdStUImm12OpValue"; let PrintMethod = "printUImm12Offset<" # Scale # ">"; + let OperandType = "OPERAND_IMMEDIATE"; } def uimm12s1 : uimm12_scaled<1>; @@ -3769,6 +3889,7 @@ def PrefetchOperand : AsmOperandClass { def prfop : Operand { let PrintMethod = "printPrefetchOp"; let ParserMatchClass = PrefetchOperand; + let OperandType = "OPERAND_IMMEDIATE"; } let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in @@ -3904,6 +4025,8 @@ class ro_extend let DecoderMethod = "DecodeMemExtend"; let EncoderMethod = "getMemExtendOpValue"; let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift); + let OperandType = "OPERAND_SHIFTED_IMMEDIATE"; + let OperandNamespace = "AArch64"; } def ro_Wextend8 : ro_extend; @@ -11759,6 +11882,7 @@ def complexrotateop : Operand, TImmLeaf= 0 && Imm <= 2 }]>> { let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">; let PrintMethod = "printComplexRotationOp<90, 0>"; + let OperandType = "OPERAND_IMMEDIATE"; } def complexrotateopodd : Operand, TImmLeaf= 0 && Imm <= 270; }], SDNodeXForm, TImmLeaf= 0 && Imm < }]>> { let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">; let PrintMethod = "printComplexRotationOp<180, 90>"; + let OperandType = "OPERAND_IMMEDIATE"; } let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in class BaseSIMDThreeSameVectorComplex size, bits<3> opcode, @@ -13159,6 +13284,7 @@ def LSLImm3ShiftOperand : AsmOperandClass { def lsl_imm3_shift_operand : Operand { let PrintMethod = "printShifter"; let ParserMatchClass = LSLImm3ShiftOperand; + let OperandType = "OPERAND_IMMEDIATE"; } // Base CPA scalar add/subtract with lsl #imm3 shift diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h index 7774d07a214b..f6d9855e7861 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h @@ -71,6 +71,8 @@ namespace AArch64 { enum OperandType { OPERAND_IMPLICIT_IMM_0 = MCOI::OPERAND_FIRST_TARGET, OPERAND_SHIFT_MSL, + OPERAND_SHIFTED_REGISTER, + OPERAND_SHIFTED_IMMEDIATE, }; } // namespace AArch64 diff --git a/llvm/test/tools/llvm-exegesis/AArch64/all-opcodes.test b/llvm/test/tools/llvm-exegesis/AArch64/all-opcodes.test index 4644b48bef1a..c2d4fb8ec642 100644 --- a/llvm/test/tools/llvm-exegesis/AArch64/all-opcodes.test +++ b/llvm/test/tools/llvm-exegesis/AArch64/all-opcodes.test @@ -2,9 +2,19 @@ # all supported opcodes and gracefully handle unsupported ones. # RUN: llvm-exegesis --mtriple=aarch64-linux-gnu --mcpu=cortex-a55 --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: -random-generator-seed=55 \ # RUN: --mode=latency --opcode-index=-1 | FileCheck %s # RUN: llvm-exegesis --mtriple=aarch64-linux-gnu --mcpu=cortex-a55 --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: -random-generator-seed=55 \ # RUN: --mode=uops --opcode-index=-1 | FileCheck %s -# 100 means "quite a lot" -# CHECK-COUNT-100: assembled_snippet: {{.*}} +# RUN: llvm-exegesis --mtriple=aarch64-linux-gnu --mcpu=neoverse-v2 --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: -random-generator-seed=2 \ +# RUN: --mode=latency --opcode-index=-1 | FileCheck --check-prefix CHECK-V2 %s +# RUN: llvm-exegesis --mtriple=aarch64-linux-gnu --mcpu=neoverse-v2 --benchmark-phase=prepare-and-assemble-snippet \ +# RUN: -random-generator-seed=2 \ +# RUN: --mode=uops --opcode-index=-1 | FileCheck --check-prefix CHECK-V2 %s + +# One snippet per llvm opcode. Not all opcodes available on any given target. +# CHECK-COUNT-2572: assembled_snippet: {{.*}} +# CHECK-V2-COUNT-4601: assembled_snippet: {{.*}} diff --git a/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s b/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s index 3ef664f89955..006394fead63 100644 --- a/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s +++ b/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s @@ -73,3 +73,109 @@ FPCR-ASM: movi d{{[0-9]+}}, #0000000000000000 FPCR-ASM-NEXT: mov x8, #0x0 FPCR-ASM-NEXT: msr FPCR, x8 FPCR-ASM-NEXT: bfcvt h{{[0-9]+}}, s{{[0-9]+}} + +## NZCV Register Class Initialization Testcase +RUN: llvm-exegesis -mtriple=aarch64 -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=ADCSWr --benchmark-phase=assemble-measured-code 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=NZCV-ASM < %t.s +NZCV-ASM: : +NZCV-ASM: mrs x8, NZCV +NZCV-ASM-NEXT: mov x9, #0xf0000000 +NZCV-ASM-NEXT: bic x8, x8, x9 +NZCV-ASM-NEXT: msr NZCV, x8 +NZCV-ASM-NEXT: adcs w{{[0-9]+}}, w{{[0-9]+}}, w{{[0-9]+}} + +## FFR Register Class Initialization Testcase +RUN: llvm-exegesis -mtriple=aarch64 -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=GLDFF1B_D --benchmark-phase=assemble-measured-code 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=FFR-ASM < %t.s +FFR-ASM: : +FFR-ASM: setffr +FFR-ASM-NEXT: ldff1b { z{{[0-9]+}}.d }, p{{[0-9]+}}/z, [x{{[0-9]+}}, z{{[0-9]+}}.d] + +# NOTE: Multi-register classes below can wrap around, e.g. { v31.1d, v0.1d } +# FileCheck cant handle this constraint and '--random-generator-seed=' +# can't be used either as the implementation relies on uniform_int_distribution +# which produces inconsistent results across libc++ implementations. + +## WSeqPair Register Class Initialization Testcase +RUN: llvm-exegesis -mtriple=aarch64 -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=CASPW --benchmark-phase=assemble-measured-code 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=WSEQPAIR-ASM < %t.s +WSEQPAIR-ASM: : +WSEQPAIR-ASM: mov w{{[0-9]+}}, #0x0 +WSEQPAIR-ASM-NEXT: mov w{{[0-9]+}}, #0x0 +WSEQPAIR-ASM-NEXT: mov w{{[0-9]+}}, #0x0 +WSEQPAIR-ASM-NEXT: mov w{{[0-9]+}}, #0x0 +WSEQPAIR-ASM: casp w{{[0-9]+}}, w{{[0-9]+}}, w{{[0-9]+}}, w{{[0-9]+}}, [x{{[0-9]+}}] + +## XSeqPair Register Class Initialization Testcase +RUN: llvm-exegesis -mtriple=aarch64 -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=CASPX --benchmark-phase=assemble-measured-code 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=XSEQPAIR-ASM < %t.s +XSEQPAIR-ASM: : +XSEQPAIR-ASM: mov x{{[0-9]+}}, #0x{{[0-9]+}} +XSEQPAIR-ASM-NEXT: mov x{{[0-9]+}}, #0x{{[0-9]+}} +XSEQPAIR-ASM-NEXT: mov x{{[0-9]+}}, #0x{{[0-9]+}} +XSEQPAIR-ASM-NEXT: mov x{{[0-9]+}}, #0x{{[0-9]+}} +XSEQPAIR-ASM: casp x{{[0-9]+}}, x{{[0-9]+}}, x{{[0-9]+}}, x{{[0-9]+}}, [x{{[0-9]+}}] + +## DD Register Class Initialization Testcase +RUN: llvm-exegesis -mtriple=aarch64 -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=ST1Twov1d_POST --benchmark-phase=assemble-measured-code 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=DD-ASM < %t.s +DD-ASM: : +DD-ASM: movi d{{[0-9]+}}, #0000000000000000 +DD-ASM-NEXT: movi d{{[0-9]+}}, #0000000000000000 +DD-ASM: st1 { v{{[0-9]+}}.1d, v{{[0-9]+}}.1d }, [x{{[0-9]+}}], x{{[0-9]+}} + +## DDD Register Class Initialization Testcase +RUN: llvm-exegesis -mtriple=aarch64 -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=ST1Threev1d_POST --benchmark-phase=assemble-measured-code 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=DDD-ASM < %t.s +DDD-ASM: : +DDD-ASM: movi d{{[0-9]+}}, #0000000000000000 +DDD-ASM-NEXT: movi d{{[0-9]+}}, #0000000000000000 +DDD-ASM-NEXT: movi d{{[0-9]+}}, #0000000000000000 +DDD-ASM: st1 { v{{[0-9]+}}.1d, v{{[0-9]+}}.1d, v{{[0-9]+}}.1d }, [x{{[0-9]+}}], x{{[0-9]+}} + +## DDDD Register Class Initialization Testcase +RUN: llvm-exegesis -mtriple=aarch64 -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=ST1Fourv1d_POST --benchmark-phase=assemble-measured-code 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=DDDD-ASM < %t.s +DDDD-ASM: : +DDDD-ASM: movi d{{[0-9]+}}, #0000000000000000 +DDDD-ASM-NEXT: movi d{{[0-9]+}}, #0000000000000000 +DDDD-ASM-NEXT: movi d{{[0-9]+}}, #0000000000000000 +DDDD-ASM-NEXT: movi d{{[0-9]+}}, #0000000000000000 +DDDD-ASM: st1 { v{{[0-9]+}}.1d, v{{[0-9]+}}.1d, v{{[0-9]+}}.1d, v{{[0-9]+}}.1d }, [x{{[0-9]+}}], x{{[0-9]+}} + +## QQ Register Class Initialization Testcase +RUN: llvm-exegesis -mtriple=aarch64 -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=ST1Twov16b_POST --benchmark-phase=assemble-measured-code 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=QQ-ASM < %t.s +QQ-ASM: : +QQ-ASM: movi v{{[0-9]+}}.2d, #0000000000000000 +QQ-ASM-NEXT: movi v{{[0-9]+}}.2d, #0000000000000000 +QQ-ASM: st1 { v{{[0-9]+}}.16b, v{{[0-9]+}}.16b }, [x{{[0-9]+}}], x{{[0-9]+}} + +## QQQ Register Class Initialization Testcase +RUN: llvm-exegesis -mtriple=aarch64 -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=ST1Threev16b_POST --benchmark-phase=assemble-measured-code 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=QQQ-ASM < %t.s +QQQ-ASM: : +QQQ-ASM: movi v{{[0-9]+}}.2d, #0000000000000000 +QQQ-ASM-NEXT: movi v{{[0-9]+}}.2d, #0000000000000000 +QQQ-ASM-NEXT: movi v{{[0-9]+}}.2d, #0000000000000000 +QQQ-ASM: st1 { v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b }, [x{{[0-9]+}}], x{{[0-9]+}} + +## QQQQ Register Class Initialization Testcase +RUN: llvm-exegesis -mtriple=aarch64 -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=ST1Fourv16b_POST --benchmark-phase=assemble-measured-code 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=QQQQ-ASM < %t.s +QQQQ-ASM: : +QQQQ-ASM: movi v{{[0-9]+}}.2d, #0000000000000000 +QQQQ-ASM-NEXT: movi v{{[0-9]+}}.2d, #0000000000000000 +QQQQ-ASM-NEXT: movi v{{[0-9]+}}.2d, #0000000000000000 +QQQQ-ASM-NEXT: movi v{{[0-9]+}}.2d, #0000000000000000 +QQQQ-ASM: st1 { v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b, v{{[0-9]+}}.16b }, [x{{[0-9]+}}], x{{[0-9]+}} diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp index 0e73adab15d8..8e324d0d8fee 100644 --- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp @@ -70,6 +70,13 @@ static MCInst loadPPRImmediate(MCRegister Reg, unsigned RegBitWidth, .addImm(31); // All lanes true for 16 bits } +static MCInst loadFFRImmediate(MCRegister Reg, unsigned RegBitWidth, + const APInt &Value) { + assert(Value.getZExtValue() == 0 && "Expected initialisation value 0"); + // For first-fault register FFR, we set it to a true + return MCInstBuilder(AArch64::SETFFR); +} + // Generates instructions to load an immediate value into an FPCR register. static std::vector loadFPCRImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) { @@ -80,6 +87,42 @@ loadFPCRImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) { return {LoadImm, MoveToFPCR}; } +// Generates instructions to load an immediate value into a pair of W registers +static std::vector loadWSeqPairImmediate(MCRegister Reg, + unsigned RegBitWidth, + const APInt &Value) { + MCRegister EvenReg = (Reg - AArch64::W0_W1) * 2 + AArch64::W0 + 0; + MCRegister OddReg = (Reg - AArch64::W0_W1) * 2 + AArch64::W0 + 1; + assert(Value.getBitWidth() <= RegBitWidth && + "Value must fit in the Register"); + + MCInst LoadEven = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth)) + .addReg(EvenReg) + .addImm(Value.getZExtValue()); + MCInst LoadOdd = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth)) + .addReg(OddReg) + .addImm(Value.getZExtValue()); + return {LoadEven, LoadOdd}; +} + +// Generates instructions to load an immediate value into a pair of X registers +static std::vector loadXSeqPairImmediate(MCRegister Reg, + unsigned RegBitWidth, + const APInt &Value) { + MCRegister EvenReg = (Reg - AArch64::X0_X1) * 2 + AArch64::X0 + 0; + MCRegister OddReg = (Reg - AArch64::X0_X1) * 2 + AArch64::X0 + 1; + assert(Value.getBitWidth() <= RegBitWidth && + "Value must fit in the Register"); + + MCInst LoadEven = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth)) + .addReg(EvenReg) + .addImm(Value.getZExtValue()); + MCInst LoadOdd = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth)) + .addReg(OddReg) + .addImm(Value.getZExtValue()); + return {LoadEven, LoadOdd}; +} + // Fetch base-instruction to load an FP immediate value into a register. static unsigned getLoadFPImmediateOpcode(unsigned RegBitWidth) { switch (RegBitWidth) { @@ -106,6 +149,59 @@ static MCInst loadFPImmediate(MCRegister Reg, unsigned RegBitWidth, return Instructions; } +// Generates instructions to load an immediate value into a DD, DDD, DDDD, +// QQ, QQQ or QQQQ Reg +static std::vector +loadDQ234RegImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value, + MCRegister BaseReg, unsigned RegCount) { + MCRegister RegDorQ0 = AArch64::D0; + if (RegBitWidth == 128) + RegDorQ0 = AArch64::Q0; + + MCRegister RegDQ0 = RegDorQ0 + ((Reg - BaseReg + 0) % 32); + MCRegister RegDQ1 = RegDorQ0 + ((Reg - BaseReg + 1) % 32); + MCRegister RegDQ2 = RegDorQ0 + ((Reg - BaseReg + 2) % 32); + MCRegister RegDQ3 = RegDorQ0 + ((Reg - BaseReg + 3) % 32); + + MCInst LoadDQ0 = loadFPImmediate(RegDQ0, RegBitWidth, Value); + MCInst LoadDQ1 = loadFPImmediate(RegDQ1, RegBitWidth, Value); + if (RegCount == 2) + return {LoadDQ0, LoadDQ1}; + MCInst LoadDQ2 = loadFPImmediate(RegDQ2, RegBitWidth, Value); + if (RegCount == 3) + return {LoadDQ0, LoadDQ1, LoadDQ2}; + MCInst LoadDQ3 = loadFPImmediate(RegDQ3, RegBitWidth, Value); + assert((RegCount == 4) && "ExpectedRegCount 2, 3 or 4"); + return {LoadDQ0, LoadDQ1, LoadDQ2, LoadDQ3}; +} + +// Generates instructions to load immediate in the flags register +static std::vector +loadNZCVImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) { + MCRegister TempReg1 = AArch64::X8; + MCRegister TempReg2 = AArch64::X9; + + MCInst MoveFromNZCV = + MCInstBuilder(AArch64::MRS).addReg(TempReg1).addImm(AArch64SysReg::NZCV); + MCInst LoadMask = + MCInstBuilder(AArch64::MOVi64imm).addReg(TempReg2).addImm(0xf0000000); + MCInst BitClear = MCInstBuilder(AArch64::BICXrr) + .addReg(TempReg1) + .addReg(TempReg1) + .addReg(TempReg2); + MCInst MoveToNZCV = + MCInstBuilder(AArch64::MSR).addImm(AArch64SysReg::NZCV).addReg(TempReg1); + + if (Value.getZExtValue() == 0) + return {MoveFromNZCV, LoadMask, BitClear, MoveToNZCV}; + + MCInst OrrMask = MCInstBuilder(AArch64::ORRXrr) + .addReg(TempReg1) + .addReg(TempReg1) + .addImm(Value.getZExtValue()); + return {MoveFromNZCV, LoadMask, BitClear, OrrMask, MoveToNZCV}; +} + #include "AArch64GenExegesis.inc" namespace { @@ -146,6 +242,30 @@ private: return {loadZPRImmediate(Reg, 128, Value)}; if (Reg == AArch64::FPCR) return {loadFPCRImmediate(Reg, 32, Value)}; + if (Reg == AArch64::NZCV) + return {loadNZCVImmediate(Reg, 32, Value)}; + if (Reg == AArch64::FFR) + return {loadFFRImmediate(Reg, 32, Value)}; + if (AArch64::WSeqPairsClassRegClass.contains(Reg)) + return {loadWSeqPairImmediate(Reg, 32, Value)}; + if (AArch64::XSeqPairsClassRegClass.contains(Reg)) + return {loadXSeqPairImmediate(Reg, 64, Value)}; + if (AArch64::DDRegClass.contains(Reg)) + return loadDQ234RegImmediate(Reg, 64, Value, AArch64::D0_D1, 2); + if (AArch64::DDDRegClass.contains(Reg)) + return loadDQ234RegImmediate(Reg, 64, Value, AArch64::D0_D1_D2, 3); + if (AArch64::DDDDRegClass.contains(Reg)) + return loadDQ234RegImmediate(Reg, 64, Value, AArch64::D0_D1_D2_D3, 4); + if (AArch64::QQRegClass.contains(Reg)) + return loadDQ234RegImmediate(Reg, 128, Value, AArch64::Q0_Q1, 2); + if (AArch64::QQQRegClass.contains(Reg)) + return loadDQ234RegImmediate(Reg, 128, Value, AArch64::Q0_Q1_Q2, 3); + if (AArch64::QQQQRegClass.contains(Reg)) + return loadDQ234RegImmediate(Reg, 128, Value, AArch64::Q0_Q1_Q2_Q3, 4); + // TODO if (AArch64::PNRRegClass.contains(Reg)) + // TODO if (AArch64::ZPRRegClass.contains(Reg)) + // TODO if (AArch64::ZPR2RegClass.contains(Reg)) + // TODO if (AArch64::ZPR2StridedOrContiguousRegClass.contains(Reg)) errs() << "setRegTo is not implemented, results will be unreliable\n"; return {}; @@ -224,6 +344,13 @@ Error ExegesisAArch64Target::randomizeTargetMCOperand( case llvm::AArch64::OPERAND_IMPLICIT_IMM_0: AssignedValue = MCOperand::createImm(0); return Error::success(); + case llvm::AArch64::OPERAND_SHIFTED_REGISTER: + // TODO it would be better if these operands were randomized + AssignedValue = MCOperand::createReg(0); + return Error::success(); + case llvm::AArch64::OPERAND_SHIFTED_IMMEDIATE: + AssignedValue = MCOperand::createImm(0); + return Error::success(); case MCOI::OperandType::OPERAND_PCREL: AssignedValue = MCOperand::createImm(8); return Error::success();