Index: llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td +++ llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td @@ -193,6 +193,7 @@ def SImm10s8Operand : AsmOperandClass { let Name = "SImm10s8"; let DiagnosticType = "InvalidMemoryIndexedSImm10"; + let PredicateMethod = "isSImmScaled<10, 8>"; } //===----------------------------------------------------------------------===// @@ -221,19 +222,23 @@ let ParserMatchClass = AdrOperand; } +class SImmOperand : AsmOperandClass { + let Name = "SImm" # width; + let DiagnosticType = "InvalidMemoryIndexedSImm" # width; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isSImm<" # width # ">"; +} + def simm10Scaled : Operand { let ParserMatchClass = SImm10s8Operand; let DecoderMethod = "DecodeSImm<10>"; let PrintMethod = "printImmScale<8>"; } -// simm9 predicate - True if the immediate is in the range [-256, 255]. -def SImm9Operand : AsmOperandClass { - let Name = "SImm9"; - let DiagnosticType = "InvalidMemoryIndexedSImm9"; -} +def SImm9Operand : SImmOperand<9>; def simm9 : Operand, ImmLeaf= -256 && Imm < 256; }]> { let ParserMatchClass = SImm9Operand; + let DecoderMethod = "DecodeSImm<9>"; } // simm7sN predicate - True if the immediate is a multiple of N in the range @@ -241,6 +246,7 @@ class SImm7Scaled : AsmOperandClass { let Name = "SImm7s" # Scale; let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm7"; + let PredicateMethod = "isSImmScaled<7, " # Scale # ">"; } def SImm7s4Operand : SImm7Scaled<4>; Index: llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -470,50 +470,22 @@ bool isImm() const override { return Kind == k_Immediate; } bool isMem() const override { return false; } - bool isSImm9() const { - if (!isImm()) - return false; - const MCConstantExpr *MCE = dyn_cast(getImm()); - if (!MCE) - return false; - int64_t Val = MCE->getValue(); - return (Val >= -256 && Val < 256); - } - bool isSImm10s8() const { - if (!isImm()) - return false; - const MCConstantExpr *MCE = dyn_cast(getImm()); - if (!MCE) - return false; - int64_t Val = MCE->getValue(); - return (Val >= -4096 && Val < 4089 && (Val & 7) == 0); - } - bool isSImm7s4() const { - if (!isImm()) - return false; - const MCConstantExpr *MCE = dyn_cast(getImm()); - if (!MCE) - return false; - int64_t Val = MCE->getValue(); - return (Val >= -256 && Val <= 252 && (Val & 3) == 0); - } - bool isSImm7s8() const { - if (!isImm()) - return false; - const MCConstantExpr *MCE = dyn_cast(getImm()); - if (!MCE) - return false; - int64_t Val = MCE->getValue(); - return (Val >= -512 && Val <= 504 && (Val & 7) == 0); - } - bool isSImm7s16() const { + + template bool isSImm() const { return isSImmScaled(); } + + template bool isSImmScaled() const { if (!isImm()) return false; const MCConstantExpr *MCE = dyn_cast(getImm()); if (!MCE) return false; + + int64_t Shift = Bits - 1; + int64_t MinVal = (int64_t(1) << Shift) * -Scale; + int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale; + int64_t Val = MCE->getValue(); - return (Val >= -1024 && Val <= 1008 && (Val & 15) == 0); + return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0; } bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const { @@ -1081,7 +1053,7 @@ // ambiguity in the matcher. template bool isSImm9OffsetFB() const { - return isSImm9() && !isUImm12Offset(); + return isSImm<9>() && !isUImm12Offset(); } bool isAdrpLabel() const {