aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSander de Smalen <sander.desmalen@arm.com>2018-05-25 09:47:52 +0000
committerSander de Smalen <sander.desmalen@arm.com>2018-05-25 09:47:52 +0000
commit537da199f4256a5ee6c679cef8141b58dcad06df (patch)
treeac820611b23eb1ad56913a98939afed14117046c
parent8c15b1c473735b61f3c4487c4b553bdb01469750 (diff)
[AArch64][SVE] Asm: Support for DUP (immediate) instructions.
Unpredicated copy of optionally-shifted immediate to SVE vector, along with MOV-aliases. This patch contains parsing and printing support for cpy_imm8_opt_lsl_(i8|i16|i32|i64). This operand allows a signed value in the range -128 to +127. For element widths of 16 bits or higher it may also be a signed multiple of 256 in the range -32768 to +32512. For element-width of 8 bits a range of -128 to 255 is accepted, since a copy of a byte can be considered either signed/unsigned. Note: This patch renames tryParseAddSubImm() -> tryParseImmWithOptionalShift() and moves the behaviour of trying to shift a plain immediate by an allowed shift-value to its addImmWithOptionalShiftOperands() method, so that the parsing itself is generic and allows immediates from multiple shifted operands. This is done because an immediate can be divisible by both shifted operands. Reviewers: rengolin, fhahn, samparker, SjoerdMeijer, javed.absar Reviewed By: fhahn Differential Revision: https://reviews.llvm.org/D47309 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@333263 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/AArch64/AArch64InstrFormats.td6
-rw-r--r--lib/Target/AArch64/AArch64SVEInstrInfo.td3
-rw-r--r--lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp108
-rw-r--r--lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp15
-rw-r--r--lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp43
-rw-r--r--lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h4
-rw-r--r--lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h11
-rw-r--r--lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp22
-rw-r--r--lib/Target/AArch64/SVEInstrFormats.td74
-rw-r--r--test/MC/AArch64/SVE/dup-diagnostics.s119
-rw-r--r--test/MC/AArch64/SVE/dup.s126
-rw-r--r--test/MC/AArch64/SVE/mov-diagnostics.s119
-rw-r--r--test/MC/AArch64/SVE/mov.s126
13 files changed, 746 insertions, 30 deletions
diff --git a/lib/Target/AArch64/AArch64InstrFormats.td b/lib/Target/AArch64/AArch64InstrFormats.td
index 0b3da6b55a0..9e5dac5ebab 100644
--- a/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/lib/Target/AArch64/AArch64InstrFormats.td
@@ -805,11 +805,13 @@ def move_vec_shift : Operand<i32> {
let DiagnosticType = "AddSubSecondSource" in {
def AddSubImmOperand : AsmOperandClass {
let Name = "AddSubImm";
- let ParserMethod = "tryParseAddSubImm";
+ let ParserMethod = "tryParseImmWithOptionalShift";
+ let RenderMethod = "addImmWithOptionalShiftOperands<12>";
}
def AddSubImmNegOperand : AsmOperandClass {
let Name = "AddSubImmNeg";
- let ParserMethod = "tryParseAddSubImm";
+ let ParserMethod = "tryParseImmWithOptionalShift";
+ let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
}
}
// An ADD/SUB immediate shifter operand:
diff --git a/lib/Target/AArch64/AArch64SVEInstrInfo.td b/lib/Target/AArch64/AArch64SVEInstrInfo.td
index e256f5daf15..ec3d9b49a15 100644
--- a/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -20,6 +20,9 @@ let Predicates = [HasSVE] in {
defm ADD_ZPmZ : sve_int_bin_pred_arit_0<0b000, "add">;
defm SUB_ZPmZ : sve_int_bin_pred_arit_0<0b001, "sub">;
+ // Splat immediate (unpredicated)
+ defm DUP_ZI : sve_int_dup_imm<"dup">;
+
// continuous load with reg+immediate
defm LD1B_IMM : sve_mem_cld_si<0b0000, "ld1b", Z_b, ZPR8>;
defm LD1B_H_IMM : sve_mem_cld_si<0b0001, "ld1b", Z_h, ZPR16>;
diff --git a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 83d984c9e4b..8e1e73ee1f3 100644
--- a/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -133,7 +133,7 @@ private:
OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
- OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
+ OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
bool tryParseNeonVectorRegister(OperandVector &Operands);
OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
@@ -636,6 +636,27 @@ public:
bool isShiftedImm() const { return Kind == k_ShiftedImm; }
+ /// Returns the immediate value as a pair of (imm, shift) if the immediate is
+ /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
+ /// immediate that can be shifted by 'Shift'.
+ template <unsigned Width>
+ Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
+ if (isShiftedImm() && Width == getShiftedImmShift())
+ if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
+ return std::make_pair(CE->getValue(), Width);
+
+ if (isImm())
+ if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
+ int64_t Val = CE->getValue();
+ if ((Val != 0) && ((Val >> Width) << Width) == Val)
+ return std::make_pair(Val >> Width, Width);
+ else
+ return std::make_pair(Val, 0u);
+ }
+
+ return {};
+ }
+
bool isAddSubImm() const {
if (!isShiftedImm() && !isImm())
return false;
@@ -673,8 +694,8 @@ public:
}
// If it's a constant, it should be a real immediate in range:
- if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
- return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
+ if (auto ShiftedVal = getShiftedVal<12>())
+ return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
// If it's an expression, we hope for the best and let the fixup/relocation
// code deal with it.
@@ -701,6 +722,26 @@ public:
return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
}
+ // Signed value in the range -128 to +127. For element widths of
+ // 16 bits or higher it may also be a signed multiple of 256 in the
+ // range -32768 to +32512.
+ // For element-width of 8 bits a range of -128 to 255 is accepted,
+ // since a copy of a byte can be either signed/unsigned.
+ template <typename T>
+ DiagnosticPredicate isSVECpyImm() const {
+ if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
+ return DiagnosticPredicateTy::NoMatch;
+
+ bool IsByte =
+ std::is_same<int8_t, typename std::make_signed<T>::type>::value;
+ if (auto ShiftedImm = getShiftedVal<8>())
+ if (!(IsByte && ShiftedImm->second) &&
+ AArch64_AM::isSVECpyImm<T>(ShiftedImm->first << ShiftedImm->second))
+ return DiagnosticPredicateTy::Match;
+
+ return DiagnosticPredicateTy::NearMatch;
+ }
+
bool isCondCode() const { return Kind == k_CondCode; }
bool isSIMDImmType10() const {
@@ -1284,9 +1325,13 @@ public:
addExpr(Inst, getImm());
}
- void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
+ template <int Shift>
+ void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
- if (isShiftedImm()) {
+ if (auto ShiftedVal = getShiftedVal<Shift>()) {
+ Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
+ Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
+ } else if (isShiftedImm()) {
addExpr(Inst, getShiftedImmVal());
Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
} else {
@@ -1295,16 +1340,14 @@ public:
}
}
- void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
+ template <int Shift>
+ void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
-
- const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
- const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
- int64_t Val = -CE->getValue();
- unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
-
- Inst.addOperand(MCOperand::createImm(Val));
- Inst.addOperand(MCOperand::createImm(ShiftAmt));
+ if (auto ShiftedVal = getShiftedVal<Shift>()) {
+ Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
+ Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
+ } else
+ llvm_unreachable("Not a shifted negative immediate");
}
void addCondCodeOperands(MCInst &Inst, unsigned N) const {
@@ -2269,9 +2312,10 @@ AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
return MatchOperand_ParseFail;
}
-/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
+/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
+/// a shift suffix, for example '#1, lsl #12'.
OperandMatchResultTy
-AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
+AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
SMLoc S = getLoc();
@@ -2285,18 +2329,9 @@ AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
if (parseSymbolicImmVal(Imm))
return MatchOperand_ParseFail;
else if (Parser.getTok().isNot(AsmToken::Comma)) {
- uint64_t ShiftAmount = 0;
- const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
- if (MCE) {
- int64_t Val = MCE->getValue();
- if (Val > 0xfff && (Val & 0xfff) == 0) {
- Imm = MCConstantExpr::create(Val >> 12, getContext());
- ShiftAmount = 12;
- }
- }
SMLoc E = Parser.getTok().getLoc();
- Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
- getContext()));
+ Operands.push_back(
+ AArch64Operand::CreateImm(Imm, S, E, getContext()));
return MatchOperand_Success;
}
@@ -2328,6 +2363,13 @@ AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
}
Parser.Lex(); // Eat the number
+ // Just in case the optional lsl #0 is used for immediates other than zero.
+ if (ShiftAmount == 0 && Imm != 0) {
+ SMLoc E = Parser.getTok().getLoc();
+ Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
+ return MatchOperand_Success;
+ }
+
SMLoc E = Parser.getTok().getLoc();
Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
S, E, getContext()));
@@ -3765,6 +3807,14 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
return Error(Loc, "immediate must be an integer in range [1, 32].");
case Match_InvalidImm1_64:
return Error(Loc, "immediate must be an integer in range [1, 64].");
+ case Match_InvalidSVECpyImm8:
+ return Error(Loc, "immediate must be an integer in range [-128, 255]"
+ " with a shift amount of 0");
+ case Match_InvalidSVECpyImm16:
+ case Match_InvalidSVECpyImm32:
+ case Match_InvalidSVECpyImm64:
+ return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
+ "multiple of 256 in range [-32768, 32512]");
case Match_InvalidIndex1:
return Error(Loc, "expected lane specifier '[1]'");
case Match_InvalidIndexB:
@@ -4293,6 +4343,10 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidImm1_16:
case Match_InvalidImm1_32:
case Match_InvalidImm1_64:
+ case Match_InvalidSVECpyImm8:
+ case Match_InvalidSVECpyImm16:
+ case Match_InvalidSVECpyImm32:
+ case Match_InvalidSVECpyImm64:
case Match_InvalidIndex1:
case Match_InvalidIndexB:
case Match_InvalidIndexH:
diff --git a/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 3a96ab6c6cb..ecb51cf695f 100644
--- a/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -207,6 +207,9 @@ static DecodeStatus DecodeSVELogicalImmInstruction(llvm::MCInst &Inst,
template<int Bits>
static DecodeStatus DecodeSImm(llvm::MCInst &Inst, uint64_t Imm,
uint64_t Address, const void *Decoder);
+template <int ElementWidth>
+static DecodeStatus DecodeImm8OptLsl(MCInst &Inst, unsigned Imm,
+ uint64_t Addr, const void *Decoder);
static bool Check(DecodeStatus &Out, DecodeStatus In) {
switch (In) {
@@ -1775,3 +1778,15 @@ static DecodeStatus DecodeSImm(llvm::MCInst &Inst, uint64_t Imm,
return Success;
}
+// Decode 8-bit signed/unsigned immediate for a given element width.
+template <int ElementWidth>
+static DecodeStatus DecodeImm8OptLsl(MCInst &Inst, unsigned Imm,
+ uint64_t Addr, const void *Decoder) {
+ unsigned Val = (uint8_t)Imm;
+ unsigned Shift = (Imm & 0x100) ? 8 : 0;
+ if (ElementWidth == 8 && Shift)
+ return Fail;
+ Inst.addOperand(MCOperand::createImm(Val));
+ Inst.addOperand(MCOperand::createImm(Shift));
+ return Success;
+}
diff --git a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
index 03f1653ffd4..1f3dc0c39b4 100644
--- a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
+++ b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
@@ -1437,3 +1437,46 @@ void AArch64InstPrinter::printSVERegOp(const MCInst *MI, unsigned OpNum,
if (suffix != 0)
O << '.' << suffix;
}
+
+template <typename T>
+void AArch64InstPrinter::printImmSVE(T Value, raw_ostream &O) {
+ typename std::make_unsigned<T>::type HexValue = Value;
+
+ if (getPrintImmHex())
+ O << '#' << formatHex((uint64_t)HexValue);
+ else
+ O << '#' << formatDec(Value);
+
+ if (CommentStream) {
+ // Do the opposite to that used for instruction operands.
+ if (getPrintImmHex())
+ *CommentStream << '=' << formatDec(HexValue) << '\n';
+ else
+ *CommentStream << '=' << formatHex((uint64_t)Value) << '\n';
+ }
+}
+
+template <typename T>
+void AArch64InstPrinter::printImm8OptLsl(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ unsigned UnscaledVal = MI->getOperand(OpNum).getImm();
+ unsigned Shift = MI->getOperand(OpNum + 1).getImm();
+ assert(AArch64_AM::getShiftType(Shift) == AArch64_AM::LSL &&
+ "Unexepected shift type!");
+
+ // #0 lsl #8 is never pretty printed
+ if ((UnscaledVal == 0) && (AArch64_AM::getShiftValue(Shift) != 0)) {
+ O << '#' << formatImm(UnscaledVal);
+ printShifter(MI, OpNum + 1, STI, O);
+ return;
+ }
+
+ T Val;
+ if (std::is_signed<T>())
+ Val = (int8_t)UnscaledVal * (1 << AArch64_AM::getShiftValue(Shift));
+ else
+ Val = (uint8_t)UnscaledVal * (1 << AArch64_AM::getShiftValue(Shift));
+
+ printImmSVE(Val, O);
+}
diff --git a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h
index bd970378b0c..4c8bf4fc826 100644
--- a/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h
+++ b/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h
@@ -57,6 +57,7 @@ protected:
raw_ostream &O);
void printImmHex(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &O);
+ template <typename T> void printImmSVE(T Value, raw_ostream &O);
void printPostIncOperand(const MCInst *MI, unsigned OpNo, unsigned Imm,
raw_ostream &O);
template <int Amount>
@@ -168,6 +169,9 @@ protected:
void printGPRSeqPairsClassOperand(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI,
raw_ostream &O);
+ template <typename T>
+ void printImm8OptLsl(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI, raw_ostream &O);
void printSVEPattern(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, raw_ostream &O);
template <char = 0>
diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h b/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
index 637aa4a9e6f..196ed427df7 100644
--- a/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
+++ b/lib/Target/AArch64/MCTargetDesc/AArch64AddressingModes.h
@@ -765,6 +765,17 @@ static inline bool isSVEMaskOfIdenticalElements(int64_t Imm) {
return all_of(Vec.Parts, [Vec](T Elem) { return Elem == Vec.Parts[0]; });
}
+/// Returns true if Imm is valid for CPY/DUP.
+template <typename T>
+static inline bool isSVECpyImm(int64_t Imm) {
+ if (std::is_same<int8_t, typename std::make_signed<T>::type>::value)
+ return uint8_t(Imm) == Imm || int8_t(Imm) == Imm;
+ else
+ return int8_t(Imm) == Imm || int16_t(Imm & ~0xff) == Imm;
+
+ llvm_unreachable("Unsupported element width");
+}
+
inline static bool isAnyMOVZMovAlias(uint64_t Value, int RegWidth) {
for (int Shift = 0; Shift <= RegWidth - 16; Shift += 16)
if ((Value & ~(0xffffULL << Shift)) == 0)
diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp b/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
index 74e98dfd183..d15c928a513 100644
--- a/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
+++ b/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp
@@ -163,6 +163,10 @@ public:
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ uint32_t getImm8OptLsl(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue,
const MCSubtargetInfo &STI) const;
@@ -509,6 +513,24 @@ AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
return MO.getImm() - 8;
}
+uint32_t
+AArch64MCCodeEmitter::getImm8OptLsl(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ // Test shift
+ auto ShiftOpnd = MI.getOperand(OpIdx + 1).getImm();
+ assert(AArch64_AM::getShiftType(ShiftOpnd) == AArch64_AM::LSL &&
+ "Unexpected shift type for imm8_opt_lsl immediate.");
+
+ unsigned ShiftVal = AArch64_AM::getShiftValue(ShiftOpnd);
+ assert((ShiftVal == 0 || ShiftVal == 8) &&
+ "Unexpected shift value for imm8_opt_lsl immediate.");
+
+ // Test immediate
+ auto Immediate = MI.getOperand(OpIdx).getImm();
+ return (Immediate & 0xff) | (ShiftVal == 0 ? 0 : (1 << ShiftVal));
+}
+
/// getMoveVecShifterOpValue - Return the encoded value for the vector move
/// shifter (MSL).
uint32_t AArch64MCCodeEmitter::getMoveVecShifterOpValue(
diff --git a/lib/Target/AArch64/SVEInstrFormats.td b/lib/Target/AArch64/SVEInstrFormats.td
index 59dcc4db7c2..ad90e50494c 100644
--- a/lib/Target/AArch64/SVEInstrFormats.td
+++ b/lib/Target/AArch64/SVEInstrFormats.td
@@ -84,7 +84,6 @@ def sve_logical_imm32 : Operand<i64> {
}];
}
-//===----------------------------------------------------------------------===//
class SVELogicalImmNotOperand<int Width> : AsmOperandClass {
let Name = "SVELogicalImm" # Width # "Not";
let DiagnosticType = "LogicalSecondSource";
@@ -104,6 +103,43 @@ def sve_logical_imm32_not : Operand<i64> {
let ParserMatchClass = SVELogicalImmNotOperand<32>;
}
+class SVEShiftedImmOperand<int ElementWidth, string Infix, string Predicate>
+ : AsmOperandClass {
+ let Name = "SVE" # Infix # "Imm" # ElementWidth;
+ let DiagnosticType = "Invalid" # Name;
+ let RenderMethod = "addImmWithOptionalShiftOperands<8>";
+ let ParserMethod = "tryParseImmWithOptionalShift";
+ let PredicateMethod = Predicate;
+}
+
+def SVECpyImmOperand8 : SVEShiftedImmOperand<8, "Cpy", "isSVECpyImm<int8_t>">;
+def SVECpyImmOperand16 : SVEShiftedImmOperand<16, "Cpy", "isSVECpyImm<int16_t>">;
+def SVECpyImmOperand32 : SVEShiftedImmOperand<32, "Cpy", "isSVECpyImm<int32_t>">;
+def SVECpyImmOperand64 : SVEShiftedImmOperand<64, "Cpy", "isSVECpyImm<int64_t>">;
+
+class imm8_opt_lsl<int ElementWidth, string printType,
+ AsmOperandClass OpndClass, code Predicate>
+ : Operand<i32>, ImmLeaf<i32, Predicate> {
+ let EncoderMethod = "getImm8OptLsl";
+ let DecoderMethod = "DecodeImm8OptLsl<" # ElementWidth # ">";
+ let PrintMethod = "printImm8OptLsl<" # printType # ">";
+ let ParserMatchClass = OpndClass;
+ let MIOperandInfo = (ops i32imm, i32imm);
+}
+
+def cpy_imm8_opt_lsl_i8 : imm8_opt_lsl<8, "int8_t", SVECpyImmOperand8, [{
+ return AArch64_AM::isSVECpyImm<int8_t>(Imm);
+}]>;
+def cpy_imm8_opt_lsl_i16 : imm8_opt_lsl<16, "int16_t", SVECpyImmOperand16, [{
+ return AArch64_AM::isSVECpyImm<int16_t>(Imm);
+}]>;
+def cpy_imm8_opt_lsl_i32 : imm8_opt_lsl<32, "int32_t", SVECpyImmOperand32, [{
+ return AArch64_AM::isSVECpyImm<int32_t>(Imm);
+}]>;
+def cpy_imm8_opt_lsl_i64 : imm8_opt_lsl<64, "int64_t", SVECpyImmOperand64, [{
+ return AArch64_AM::isSVECpyImm<int64_t>(Imm);
+}]>;
+
//===----------------------------------------------------------------------===//
// SVE PTrue - These are used extensively throughout the pattern matching so
// it's important we define them first.
@@ -352,6 +388,42 @@ multiclass sve_int_bin_pred_arit_0<bits<3> opc, string asm> {
def _D : sve_int_bin_pred_arit_log<0b11, 0b00, opc, asm, ZPR64>;
}
+//===----------------------------------------------------------------------===//
+// SVE Integer Wide Immediate - Unpredicated Group
+//===----------------------------------------------------------------------===//
+class sve_int_dup_imm<bits<2> sz8_64, string asm,
+ ZPRRegOp zprty, Operand immtype>
+: I<(outs zprty:$Zd), (ins immtype:$imm),
+ asm, "\t$Zd, $imm",
+ "",
+ []>, Sched<[]> {
+ bits<5> Zd;
+ bits<9> imm;
+ let Inst{31-24} = 0b00100101;
+ let Inst{23-22} = sz8_64;
+ let Inst{21-14} = 0b11100011;
+ let Inst{13} = imm{8}; // sh
+ let Inst{12-5} = imm{7-0}; // imm8
+ let Inst{4-0} = Zd;
+
+ let isReMaterializable = 1;
+}
+
+multiclass sve_int_dup_imm<string asm> {
+ def _B : sve_int_dup_imm<0b00, asm, ZPR8, cpy_imm8_opt_lsl_i8>;
+ def _H : sve_int_dup_imm<0b01, asm, ZPR16, cpy_imm8_opt_lsl_i16>;
+ def _S : sve_int_dup_imm<0b10, asm, ZPR32, cpy_imm8_opt_lsl_i32>;
+ def _D : sve_int_dup_imm<0b11, asm, ZPR64, cpy_imm8_opt_lsl_i64>;
+
+ def : InstAlias<"mov $Zd, $imm",
+ (!cast<Instruction>(NAME # _B) ZPR8:$Zd, cpy_imm8_opt_lsl_i8:$imm), 1>;
+ def : InstAlias<"mov $Zd, $imm",
+ (!cast<Instruction>(NAME # _H) ZPR16:$Zd, cpy_imm8_opt_lsl_i16:$imm), 1>;
+ def : InstAlias<"mov $Zd, $imm",
+ (!cast<Instruction>(NAME # _S) ZPR32:$Zd, cpy_imm8_opt_lsl_i32:$imm), 1>;
+ def : InstAlias<"mov $Zd, $imm",
+ (!cast<Instruction>(NAME # _D) ZPR64:$Zd, cpy_imm8_opt_lsl_i64:$imm), 1>;
+}
//===----------------------------------------------------------------------===//
//SVE Index Generation Group
diff --git a/test/MC/AArch64/SVE/dup-diagnostics.s b/test/MC/AArch64/SVE/dup-diagnostics.s
index f8a538117f0..bdc294fd803 100644
--- a/test/MC/AArch64/SVE/dup-diagnostics.s
+++ b/test/MC/AArch64/SVE/dup-diagnostics.s
@@ -17,3 +17,122 @@ dup z0.d, xzr
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: dup z0.d, xzr
// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// Invalid immediates
+
+dup z0.b, #0, lsl #8 // #0, lsl #8 is not valid for .b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
+// CHECK-NEXT: dup z0.b, #0, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.b, #-129
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
+// CHECK-NEXT: dup z0.b, #-129
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.b, #-1, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
+// CHECK-NEXT: dup z0.b, #-1, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.b, #256
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
+// CHECK-NEXT: dup z0.b, #256
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.b, #1, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
+// CHECK-NEXT: dup z0.b, #1, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.h, #-33024
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.h, #-33024
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.h, #-32769
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.h, #-32769
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.h, #-129, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.h, #-129, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.h, #32513
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.h, #32513
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.h, #32768
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.h, #32768
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.h, #128, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.h, #128, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.s, #-33024
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.s, #-33024
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.s, #-32769
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.s, #-32769
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.s, #-129, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.s, #-129, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.s, #32513
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.s, #32513
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.s, #32768
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.s, #32768
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.s, #128, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.s, #128, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.d, #-33024
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.d, #-33024
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.d, #-32769
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.d, #-32769
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.d, #-129, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.d, #-129, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.d, #32513
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.d, #32513
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.d, #32768
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.d, #32768
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+dup z0.d, #128, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: dup z0.d, #128, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/test/MC/AArch64/SVE/dup.s b/test/MC/AArch64/SVE/dup.s
index f045eed94ac..017aae6207e 100644
--- a/test/MC/AArch64/SVE/dup.s
+++ b/test/MC/AArch64/SVE/dup.s
@@ -54,3 +54,129 @@ dup z31.b, wsp
// CHECK-ENCODING: [0xff,0x3b,0x20,0x05]
// CHECK-ERROR: instruction requires: sve
// CHECK-UNKNOWN: ff 3b 20 05 <unknown>
+
+dup z5.b, #-128
+// CHECK-INST: mov z5.b, #-128
+// CHECK-ENCODING: [0x05,0xd0,0x38,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 05 d0 38 25 <unknown>
+
+dup z5.b, #127
+// CHECK-INST: mov z5.b, #127
+// CHECK-ENCODING: [0xe5,0xcf,0x38,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: e5 cf 38 25 <unknown>
+
+dup z5.b, #255
+// CHECK-INST: mov z5.b, #-1
+// CHECK-ENCODING: [0xe5,0xdf,0x38,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: e5 df 38 25 <unknown>
+
+dup z21.h, #-128
+// CHECK-INST: mov z21.h, #-128
+// CHECK-ENCODING: [0x15,0xd0,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 d0 78 25 <unknown>
+
+dup z21.h, #-128, lsl #8
+// CHECK-INST: mov z21.h, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 78 25 <unknown>
+
+dup z21.h, #-32768
+// CHECK-INST: mov z21.h, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 78 25 <unknown>
+
+dup z21.h, #127
+// CHECK-INST: mov z21.h, #127
+// CHECK-ENCODING: [0xf5,0xcf,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 cf 78 25 <unknown>
+
+dup z21.h, #127, lsl #8
+// CHECK-INST: mov z21.h, #32512
+// CHECK-ENCODING: [0xf5,0xef,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef 78 25 <unknown>
+
+dup z21.h, #32512
+// CHECK-INST: mov z21.h, #32512
+// CHECK-ENCODING: [0xf5,0xef,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef 78 25 <unknown>
+
+dup z21.s, #-128
+// CHECK-INST: mov z21.s, #-128
+// CHECK-ENCODING: [0x15,0xd0,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 d0 b8 25 <unknown>
+
+dup z21.s, #-128, lsl #8
+// CHECK-INST: mov z21.s, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 b8 25 <unknown>
+
+dup z21.s, #-32768
+// CHECK-INST: mov z21.s, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 b8 25 <unknown>
+
+dup z21.s, #127
+// CHECK-INST: mov z21.s, #127
+// CHECK-ENCODING: [0xf5,0xcf,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 cf b8 25 <unknown>
+
+dup z21.s, #127, lsl #8
+// CHECK-INST: mov z21.s, #32512
+// CHECK-ENCODING: [0xf5,0xef,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef b8 25 <unknown>
+
+dup z21.s, #32512
+// CHECK-INST: mov z21.s, #32512
+// CHECK-ENCODING: [0xf5,0xef,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef b8 25 <unknown>
+
+dup z21.d, #-128
+// CHECK-INST: mov z21.d, #-128
+// CHECK-ENCODING: [0x15,0xd0,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 d0 f8 25 <unknown>
+
+dup z21.d, #-128, lsl #8
+// CHECK-INST: mov z21.d, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 f8 25 <unknown>
+
+dup z21.d, #-32768
+// CHECK-INST: mov z21.d, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 f8 25 <unknown>
+
+dup z21.d, #127
+// CHECK-INST: mov z21.d, #127
+// CHECK-ENCODING: [0xf5,0xcf,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 cf f8 25 <unknown>
+
+dup z21.d, #127, lsl #8
+// CHECK-INST: mov z21.d, #32512
+// CHECK-ENCODING: [0xf5,0xef,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef f8 25 <unknown>
+
+dup z21.d, #32512
+// CHECK-INST: mov z21.d, #32512
+// CHECK-ENCODING: [0xf5,0xef,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef f8 25 <unknown>
diff --git a/test/MC/AArch64/SVE/mov-diagnostics.s b/test/MC/AArch64/SVE/mov-diagnostics.s
index fdf63beed92..af1ea8edae5 100644
--- a/test/MC/AArch64/SVE/mov-diagnostics.s
+++ b/test/MC/AArch64/SVE/mov-diagnostics.s
@@ -17,3 +17,122 @@ mov z0.d, xzr
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
// CHECK-NEXT: mov z0.d, xzr
// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}:
+
+
+// --------------------------------------------------------------------------//
+// Invalid immediates
+
+mov z0.b, #0, lsl #8 // #0, lsl #8 is not valid for .b
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
+// CHECK-NEXT: mov z0.b, #0, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.b, #-129
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
+// CHECK-NEXT: mov z0.b, #-129
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.b, #-1, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
+// CHECK-NEXT: mov z0.b, #-1, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.b, #256
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
+// CHECK-NEXT: mov z0.b, #256
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.b, #1, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 255]
+// CHECK-NEXT: mov z0.b, #1, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.h, #-33024
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.h, #-33024
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.h, #-32769
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.h, #-32769
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.h, #-129, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.h, #-129, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.h, #32513
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.h, #32513
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.h, #32768
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.h, #32768
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.h, #128, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.h, #128, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.s, #-33024
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.s, #-33024
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.s, #-32769
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.s, #-32769
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.s, #-129, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.s, #-129, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.s, #32513
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.s, #32513
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.s, #32768
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.s, #32768
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.s, #128, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.s, #128, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.d, #-33024
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.d, #-33024
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.d, #-32769
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.d, #-32769
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.d, #-129, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.d, #-129, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.d, #32513
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.d, #32513
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.d, #32768
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.d, #32768
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
+
+mov z0.d, #128, lsl #8
+// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: immediate must be an integer in range [-128, 127] or a multiple of 256 in range [-32768, 32512]
+// CHECK-NEXT: mov z0.d, #128, lsl #8
+// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
diff --git a/test/MC/AArch64/SVE/mov.s b/test/MC/AArch64/SVE/mov.s
index 5bcb5e23378..f84d0e45c1f 100644
--- a/test/MC/AArch64/SVE/mov.s
+++ b/test/MC/AArch64/SVE/mov.s
@@ -54,3 +54,129 @@ mov z31.b, wsp
// CHECK-ENCODING: [0xff,0x3b,0x20,0x05]
// CHECK-ERROR: instruction requires: sve
// CHECK-UNKNOWN: ff 3b 20 05 <unknown>
+
+mov z5.b, #-128
+// CHECK-INST: mov z5.b, #-128
+// CHECK-ENCODING: [0x05,0xd0,0x38,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 05 d0 38 25 <unknown>
+
+mov z5.b, #127
+// CHECK-INST: mov z5.b, #127
+// CHECK-ENCODING: [0xe5,0xcf,0x38,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: e5 cf 38 25 <unknown>
+
+mov z5.b, #255
+// CHECK-INST: mov z5.b, #-1
+// CHECK-ENCODING: [0xe5,0xdf,0x38,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: e5 df 38 25 <unknown>
+
+mov z21.h, #-128
+// CHECK-INST: mov z21.h, #-128
+// CHECK-ENCODING: [0x15,0xd0,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 d0 78 25 <unknown>
+
+mov z21.h, #-128, lsl #8
+// CHECK-INST: mov z21.h, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 78 25 <unknown>
+
+mov z21.h, #-32768
+// CHECK-INST: mov z21.h, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 78 25 <unknown>
+
+mov z21.h, #127
+// CHECK-INST: mov z21.h, #127
+// CHECK-ENCODING: [0xf5,0xcf,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 cf 78 25 <unknown>
+
+mov z21.h, #127, lsl #8
+// CHECK-INST: mov z21.h, #32512
+// CHECK-ENCODING: [0xf5,0xef,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef 78 25 <unknown>
+
+mov z21.h, #32512
+// CHECK-INST: mov z21.h, #32512
+// CHECK-ENCODING: [0xf5,0xef,0x78,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef 78 25 <unknown>
+
+mov z21.s, #-128
+// CHECK-INST: mov z21.s, #-128
+// CHECK-ENCODING: [0x15,0xd0,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 d0 b8 25 <unknown>
+
+mov z21.s, #-128, lsl #8
+// CHECK-INST: mov z21.s, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 b8 25 <unknown>
+
+mov z21.s, #-32768
+// CHECK-INST: mov z21.s, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 b8 25 <unknown>
+
+mov z21.s, #127
+// CHECK-INST: mov z21.s, #127
+// CHECK-ENCODING: [0xf5,0xcf,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 cf b8 25 <unknown>
+
+mov z21.s, #127, lsl #8
+// CHECK-INST: mov z21.s, #32512
+// CHECK-ENCODING: [0xf5,0xef,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef b8 25 <unknown>
+
+mov z21.s, #32512
+// CHECK-INST: mov z21.s, #32512
+// CHECK-ENCODING: [0xf5,0xef,0xb8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef b8 25 <unknown>
+
+mov z21.d, #-128
+// CHECK-INST: mov z21.d, #-128
+// CHECK-ENCODING: [0x15,0xd0,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 d0 f8 25 <unknown>
+
+mov z21.d, #-128, lsl #8
+// CHECK-INST: mov z21.d, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 f8 25 <unknown>
+
+mov z21.d, #-32768
+// CHECK-INST: mov z21.d, #-32768
+// CHECK-ENCODING: [0x15,0xf0,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: 15 f0 f8 25 <unknown>
+
+mov z21.d, #127
+// CHECK-INST: mov z21.d, #127
+// CHECK-ENCODING: [0xf5,0xcf,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 cf f8 25 <unknown>
+
+mov z21.d, #127, lsl #8
+// CHECK-INST: mov z21.d, #32512
+// CHECK-ENCODING: [0xf5,0xef,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef f8 25 <unknown>
+
+mov z21.d, #32512
+// CHECK-INST: mov z21.d, #32512
+// CHECK-ENCODING: [0xf5,0xef,0xf8,0x25]
+// CHECK-ERROR: instruction requires: sve
+// CHECK-UNKNOWN: f5 ef f8 25 <unknown>