diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -5759,6 +5759,12 @@
 include "ARMInstrNEON.td"
 
 //===----------------------------------------------------------------------===//
+// MVE Support
+//
+
+include "ARMInstrMVE.td"
+
+//===----------------------------------------------------------------------===//
 // Assembler aliases
 //
 
diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td
new file mode 100644
--- /dev/null
+++ b/llvm/lib/Target/ARM/ARMInstrMVE.td
@@ -0,0 +1,166 @@
+class MVE_MI_with_pred<dag oops, dag iops, InstrItinClass itin, string asm,
+                       string ops, string cstr, list<dag> pattern>
+  : Thumb2I<oops, iops, AddrModeNone, 4, itin, asm, !strconcat("\t", ops), cstr,
+             pattern>,
+    Requires<[HasV8_1MMainline, HasMVEInt]> {
+  let D = MVEDomain;
+  let DecoderNamespace = "MVE";
+}
+
+class t2MVEShift<string iname, dag oops, dag iops, string asm, string cstr,
+            list<dag> pattern=[]>
+  : MVE_MI_with_pred<oops, iops, NoItinerary, iname, asm, cstr, pattern> {
+  let Inst{31-20} = 0b111010100101;
+  let Inst{8} = 0b1;
+
+}
+
+class t2MVEShiftSingleReg<string iname, dag iops, string asm, string cstr,
+                    list<dag> pattern=[]>
+  : t2MVEShift<iname, (outs rGPR:$RdaDest), iops, asm, cstr, pattern> {
+  bits<4> RdaDest;
+
+  let Inst{19-16} = RdaDest{3-0};
+}
+
+class t2MVEShiftSRegImm<string iname, list<dag> pattern=[]>
+  : t2MVEShiftSingleReg<iname, (ins rGPR:$RdaSrc, long_shift:$imm),
+                     "$RdaSrc, $imm", "$RdaDest = $RdaSrc", pattern> {
+  bits<5> imm;
+
+  let Inst{15} = 0b0;
+  let Inst{14-12} = imm{4-2};
+  let Inst{11-8} = 0b1111;
+  let Inst{7-6} = imm{1-0};
+  let Inst{3-0} = 0b1111;
+}
+
+def t2SQSHL : t2MVEShiftSRegImm<"sqshl"> {
+  let Inst{5-4} = 0b11;
+}
+
+def t2SRSHR : t2MVEShiftSRegImm<"srshr"> {
+  let Inst{5-4} = 0b10;
+}
+
+def t2UQSHL : t2MVEShiftSRegImm<"uqshl"> {
+  let Inst{5-4} = 0b00;
+}
+
+def t2URSHR : t2MVEShiftSRegImm<"urshr"> {
+  let Inst{5-4} = 0b01;
+}
+
+class t2MVEShiftSRegReg<string iname, list<dag> pattern=[]>
+  : t2MVEShiftSingleReg<iname, (ins rGPR:$RdaSrc, rGPR:$Rm),
+                     "$RdaSrc, $Rm", "$RdaDest = $RdaSrc", pattern> {
+  bits<4> Rm;
+
+  let Inst{15-12} = Rm{3-0};
+  let Inst{11-8} = 0b1111;
+  let Inst{7-6} = 0b00;
+  let Inst{3-0} = 0b1101;
+}
+
+def t2SQRSHR : t2MVEShiftSRegReg<"sqrshr"> {
+  let Inst{5-4} = 0b10;
+}
+
+def t2UQRSHL : t2MVEShiftSRegReg<"uqrshl"> {
+  let Inst{5-4} = 0b00;
+}
+
+class t2MVEShiftDoubleReg<string iname, dag iops, string asm, string cstr,
+                       list<dag> pattern=[]>
+  : t2MVEShift<iname, (outs tGPREven:$RdaLo, tGPROdd:$RdaHi), iops, asm, cstr,
+            pattern> {
+  bits<4> RdaLo;
+  bits<4> RdaHi;
+
+  let Inst{19-17} = RdaLo{3-1};
+  let Inst{11-9} = RdaHi{3-1};
+}
+
+class t2MVEShiftDRegImm<string iname, list<dag> pattern=[]>
+  : t2MVEShiftDoubleReg<iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src,
+                        long_shift:$imm), "$RdaLo, $RdaHi, $imm",
+                        "$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src", pattern> {
+  bits<5> imm;
+
+  let Inst{15} = 0b0;
+  let Inst{14-12} = imm{4-2};
+  let Inst{7-6} = imm{1-0};
+  let Inst{4-0} = 0b01111;
+}
+
+class t2MVEShiftDRegReg<string iname, list<dag> pattern=[]>
+  : t2MVEShiftDoubleReg<iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm),
+                    "$RdaLo, $RdaHi, $Rm",
+                    "@earlyclobber $RdaHi,@earlyclobber $RdaLo,$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src",
+                    pattern> {
+  bits<4> Rm;
+
+  let Inst{16} = 0b0;
+  let Inst{15-12} = Rm{3-0};
+  let Inst{7-6} = 0b00;
+  let Inst{4} = 0b0;
+  let Inst{3-0} = 0b1101;
+}
+
+def t2ASRLr : t2MVEShiftDRegReg<"asrl"> {
+  let Inst{5} = 0b1;
+  // Custom decoder method because SQRSHR overlaps this encoding
+  let DecoderMethod = "DecodeMVEOverlappingLongShift";
+}
+
+def t2ASRLi : t2MVEShiftDRegImm<"asrl"> {
+  let Inst{5} = 0b1;
+}
+
+def t2LSLLr : t2MVEShiftDRegReg<"lsll"> {
+  let Inst{5} = 0b0;
+  // Custom decoder method because UQRSHL overlaps this encoding
+  let DecoderMethod = "DecodeMVEOverlappingLongShift";
+}
+
+def t2LSLLi : t2MVEShiftDRegImm<"lsll"> {
+  let Inst{5} = 0b0;
+}
+
+def t2LSRL : t2MVEShiftDRegImm<"lsrl"> {
+  let Inst{5-4} = 0b01;
+}
+
+def t2SQRSHRL : t2MVEShiftDRegReg<"sqrshrl"> {
+  let Inst{5} = 0b1;
+  let Inst{16} = 0b1;
+  // Custom decoder method because SQRSHR overlaps this encoding
+  let DecoderMethod = "DecodeMVEOverlappingLongShift";
+}
+
+def t2SQSHLL : t2MVEShiftDRegImm<"sqshll"> {
+  let Inst{5-4} = 0b11;
+  let Inst{16} = 0b1;
+}
+
+def t2SRSHRL : t2MVEShiftDRegImm<"srshrl"> {
+  let Inst{5} = 0b1;
+  let Inst{16} = 0b1;
+}
+
+def t2UQRSHLL : t2MVEShiftDRegReg<"uqrshll"> {
+  let Inst{5} = 0b0;
+  let Inst{16} = 0b1;
+  // Custom decoder method because UQRSHL overlaps this encoding
+  let DecoderMethod = "DecodeMVEOverlappingLongShift";
+}
+
+def t2UQSHLL : t2MVEShiftDRegImm<"uqshll"> {
+  let Inst{5} = 0b0;
+  let Inst{16} = 0b1;
+}
+
+def t2URSHRL : t2MVEShiftDRegImm<"urshrl"> {
+  let Inst{5-4} = 0b01;
+  let Inst{16} = 0b1;
+}
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -39,6 +39,16 @@
   let DecoderMethod = "DecodeT2ShifterImmOperand";
 }
 
+def mve_shift_imm : AsmOperandClass {
+  let Name = "MVELongShift";
+  let RenderMethod = "addImmOperands";
+  let DiagnosticString = "operand must be an immediate in the range [1,32]";
+}
+def long_shift : Operand<i32> {
+  let ParserMatchClass = mve_shift_imm;
+  let DecoderMethod = "DecodeLongShiftOperand";
+}
+
 // Shifted operands. No register controlled shifts for Thumb2.
 // Note: We do not support rrx shifted operands yet.
 def t2_so_reg : Operand<i32>,    // reg imm
diff --git a/llvm/lib/Target/ARM/ARMRegisterInfo.td b/llvm/lib/Target/ARM/ARMRegisterInfo.td
--- a/llvm/lib/Target/ARM/ARMRegisterInfo.td
+++ b/llvm/lib/Target/ARM/ARMRegisterInfo.td
@@ -331,6 +331,20 @@
   }];
 }
 
+def tGPROdd : RegisterClass<"ARM", [i32], 32, (add R1, R3, R5, R7, R9, R11)> {
+  let AltOrders = [(and tGPROdd, tGPR)];
+  let AltOrderSelect = [{
+      return MF.getSubtarget<ARMSubtarget>().isThumb1Only();
+  }];
+}
+
+def tGPREven : RegisterClass<"ARM", [i32], 32, (add R0, R2, R4, R6, R8, R10, R12, LR)> {
+  let AltOrders = [(and tGPREven, tGPR)];
+  let AltOrderSelect = [{
+      return MF.getSubtarget<ARMSubtarget>().isThumb1Only();
+  }];
+}
+
 // Condition code registers.
 def CCR : RegisterClass<"ARM", [i32], 32, (add CPSR)> {
   let CopyCost = -1;  // Don't allow copying of status registers.
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -2048,6 +2048,15 @@
     return (Value % Angle == Remainder && Value <= 270);
   }
 
+  bool isMVELongShift() const {
+    if (!isImm()) return false;
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    // Must be a constant.
+    if (!CE) return false;
+    uint64_t Value = CE->getValue();
+    return Value >= 1 && Value <= 32;
+  }
+
   bool isITCondCodeNoAL() const {
     if (!isITCondCode()) return false;
     auto CC = (ARMCC::CondCodes) getCondCode();
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -146,6 +146,10 @@
                                    uint64_t Address, const void *Decoder);
 static DecodeStatus DecodeCLRMGPRRegisterClass(MCInst &Inst, unsigned RegNo,
                                    uint64_t Address, const void *Decoder);
+static DecodeStatus DecodetGPROddRegisterClass(MCInst &Inst, unsigned RegNo,
+                                   uint64_t Address, const void *Decoder);
+static DecodeStatus DecodetGPREvenRegisterClass(MCInst &Inst, unsigned RegNo,
+                                   uint64_t Address, const void *Decoder);
 static DecodeStatus DecodeGPRnopcRegisterClass(MCInst &Inst,
                                                unsigned RegNo, uint64_t Address,
                                                const void *Decoder);
@@ -432,6 +436,9 @@
                                           const void *Decoder);
 static DecodeStatus DecodeLOLoop(MCInst &Inst, unsigned Insn, uint64_t Address,
                                  const void *Decoder);
+static DecodeStatus DecodeLongShiftOperand(MCInst &Inst, unsigned Val,
+                                           uint64_t Address,
+                                           const void *Decoder);
 static DecodeStatus DecodeVSCCLRM(MCInst &Inst, unsigned Insn, uint64_t Address,
                                   const void *Decoder);
 static DecodeStatus DecodeVSTRVLDR_SYSREG_off(MCInst &Inst, unsigned Insn,
@@ -443,6 +450,8 @@
 static DecodeStatus DecodeVSTRVLDR_SYSREG_post(MCInst &Inst, unsigned Insn,
                                               uint64_t Address,
                                               const void *Decoder);
+static DecodeStatus DecodeMVEOverlappingLongShift(MCInst &Inst, unsigned Insn, uint64_t Address,
+                                                const void *Decoder);
 #include "ARMGenDisassemblerTables.inc"
 
 static MCDisassembler *createARMDisassembler(const Target &T,
@@ -806,6 +815,15 @@
 
   uint32_t Insn32 =
       (Bytes[3] << 8) | (Bytes[2] << 0) | (Bytes[1] << 24) | (Bytes[0] << 16);
+
+  Result =
+      decodeInstruction(DecoderTableMVE32, MI, Insn32, Address, this, STI);
+  if (Result != MCDisassembler::Fail) {
+    Size = 4;
+    Check(Result, AddThumbPredicate(MI));
+    return Result;
+  }
+
   Result =
       decodeInstruction(DecoderTableThumb32, MI, Insn32, Address, this, STI);
   if (Result != MCDisassembler::Fail) {
@@ -5647,6 +5665,39 @@
   return S;
 }
 
+static DecodeStatus DecodeLongShiftOperand(MCInst &Inst, unsigned Val,
+                                           uint64_t Address,
+                                           const void *Decoder) {
+  DecodeStatus S = MCDisassembler::Success;
+
+  if (Val == 0)
+    Val = 32;
+
+  Inst.addOperand(MCOperand::createImm(Val));
+
+  return S;
+}
+
+static DecodeStatus DecodetGPROddRegisterClass(MCInst &Inst, unsigned RegNo,
+                                   uint64_t Address, const void *Decoder) {
+  if ((RegNo) + 1 > 11)
+    return MCDisassembler::Fail;
+
+  unsigned Register = GPRDecoderTable[(RegNo) + 1];
+  Inst.addOperand(MCOperand::createReg(Register));
+  return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodetGPREvenRegisterClass(MCInst &Inst, unsigned RegNo,
+                                   uint64_t Address, const void *Decoder) {
+  if ((RegNo) > 14)
+    return MCDisassembler::Fail;
+
+  unsigned Register = GPRDecoderTable[(RegNo)];
+  Inst.addOperand(MCOperand::createReg(Register));
+  return MCDisassembler::Success;
+}
+
 static DecodeStatus DecodeVSCCLRM(MCInst &Inst, unsigned Insn, uint64_t Address,
                                   const void *Decoder) {
   DecodeStatus S = MCDisassembler::Success;
@@ -5783,3 +5834,69 @@
 
   return S;
 }
+
+static DecodeStatus DecodeMVEOverlappingLongShift(
+  MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) {
+  DecodeStatus S = MCDisassembler::Success;
+
+  unsigned RdaLo = fieldFromInstruction(Insn, 17, 3) << 1;
+  unsigned RdaHi = fieldFromInstruction(Insn, 9, 3) << 1;
+  unsigned Rm = fieldFromInstruction(Insn, 12, 4);
+
+  if (RdaHi == 14) {
+    // This value of RdaHi (really indicating pc, because RdaHi has to
+    // be an odd-numbered register, so the low bit will be set by the
+    // decode function below) indicates that we must decode as SQRSHR
+    // or UQRSHL, which both have a single Rda register field with all
+    // four bits.
+    unsigned Rda = fieldFromInstruction(Insn, 16, 4);
+
+    switch (Inst.getOpcode()) {
+      case ARM::t2ASRLr:
+      case ARM::t2SQRSHRL:
+        Inst.setOpcode(ARM::t2SQRSHR);
+        break;
+      case ARM::t2LSLLr:
+      case ARM::t2UQRSHLL:
+        Inst.setOpcode(ARM::t2UQRSHL);
+        break;
+      default:
+        llvm_unreachable("Unexpected starting opcode!");
+    }
+
+    // Rda as output parameter
+    if (!Check(S, DecoderGPRRegisterClass(Inst, Rda, Address, Decoder)))
+      return MCDisassembler::Fail;
+
+    // Rda again as input parameter
+    if (!Check(S, DecoderGPRRegisterClass(Inst, Rda, Address, Decoder)))
+      return MCDisassembler::Fail;
+
+    // Rm, the amount to shift by
+    if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
+      return MCDisassembler::Fail;
+
+    return S;
+  }
+
+  // Otherwise, we decode as whichever opcode our caller has already
+  // put into Inst. Those all look the same:
+
+  // RdaLo,RdaHi as output parameters
+  if (!Check(S, DecodetGPREvenRegisterClass(Inst, RdaLo, Address, Decoder)))
+    return MCDisassembler::Fail;
+  if (!Check(S, DecodetGPROddRegisterClass(Inst, RdaHi, Address, Decoder)))
+    return MCDisassembler::Fail;
+
+  // RdaLo,RdaHi again as input parameters
+  if (!Check(S, DecodetGPREvenRegisterClass(Inst, RdaLo, Address, Decoder)))
+    return MCDisassembler::Fail;
+  if (!Check(S, DecodetGPROddRegisterClass(Inst, RdaHi, Address, Decoder)))
+    return MCDisassembler::Fail;
+
+  // Rm, the amount to shift by
+  if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
+    return MCDisassembler::Fail;
+
+  return S;
+}
diff --git a/llvm/test/MC/ARM/mve-scalar-shift.s b/llvm/test/MC/ARM/mve-scalar-shift.s
new file mode 100644
--- /dev/null
+++ b/llvm/test/MC/ARM/mve-scalar-shift.s
@@ -0,0 +1,145 @@
+# RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+mve -show-encoding  < %s \
+# RUN:   | FileCheck --check-prefix=CHECK-NOFP %s
+# RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+mve.fp,+fp64 -show-encoding  < %s 2>%t \
+# RUN:   | FileCheck --check-prefix=CHECK %s
+# RUN:     FileCheck --check-prefix=ERROR < %t %s
+
+# CHECK: asrl    r0, r1, #23  @ encoding: [0x50,0xea,0xef,0x51]
+# CHECK-NOFP: asrl    r0, r1, #23  @ encoding: [0x50,0xea,0xef,0x51]
+asrl    r0, r1, #23
+
+# CHECK: asrl    lr, r1, #27  @ encoding: [0x5e,0xea,0xef,0x61]
+# CHECK-NOFP: asrl    lr, r1, #27  @ encoding: [0x5e,0xea,0xef,0x61]
+asrl    lr, r1, #27
+
+# CHECK: it eq @ encoding: [0x08,0xbf]
+# CHECK-NEXT: asrleq    lr, r1, #27  @ encoding: [0x5e,0xea,0xef,0x61]
+# CHECK-NOFP: it eq @ encoding: [0x08,0xbf]
+# CHECK-NOFP-NEXT: asrleq    lr, r1, #27  @ encoding: [0x5e,0xea,0xef,0x61]
+it eq
+asrleq    lr, r1, #27
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid instruction
+asrl    r3, r2, #33
+
+# ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: operand must be an immediate in the range [1,32]
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: operand must be a register in range [r0, r12] or r14
+asrl    r0, r1, #33
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction
+asrl    r0, r0, #32
+
+# CHECK: asrl    r0, r1, r4  @ encoding: [0x50,0xea,0x2d,0x41]
+# CHECK-NOFP: asrl    r0, r1, r4  @ encoding: [0x50,0xea,0x2d,0x41]
+asrl    r0, r1, r4
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction
+asrl    r0, r0, r4
+
+# CHECK: cinc    lr, r2, lo  @ encoding: [0x52,0xea,0x22,0x9e]
+# CHECK-NOFP: cinc    lr, r2, lo  @ encoding: [0x52,0xea,0x22,0x9e]
+csinc   lr, r2, r2, hs
+
+# CHECK: cinc    lr, r7, pl  @ encoding: [0x57,0xea,0x47,0x9e]
+# CHECK-NOFP: cinc    lr, r7, pl  @ encoding: [0x57,0xea,0x47,0x9e]
+cinc    lr, r7, pl
+
+# CHECK: cinv    lr, r12, hs  @ encoding: [0x5c,0xea,0x3c,0xae]
+# CHECK-NOFP: cinv    lr, r12, hs  @ encoding: [0x5c,0xea,0x3c,0xae]
+cinv    lr, r12, hs
+
+# CHECK: cneg    lr, r10, hs  @ encoding: [0x5a,0xea,0x3a,0xbe]
+# CHECK-NOFP: cneg    lr, r10, hs  @ encoding: [0x5a,0xea,0x3a,0xbe]
+csneg   lr, r10, r10, lo
+
+# CHECK: csel    r9, r9, r11, vc  @ encoding: [0x59,0xea,0x7b,0x89]
+# CHECK-NOFP: csel    r9, r9, r11, vc  @ encoding: [0x59,0xea,0x7b,0x89]
+csel    r9, r9, r11, vc
+
+# CHECK: cset    lr, eq  @ encoding: [0x5f,0xea,0x1f,0x9e]
+# CHECK-NOFP: cset    lr, eq  @ encoding: [0x5f,0xea,0x1f,0x9e]
+cset    lr, eq
+
+# CHECK: csetm   lr, hs  @ encoding: [0x5f,0xea,0x3f,0xae]
+# CHECK-NOFP: csetm   lr, hs  @ encoding: [0x5f,0xea,0x3f,0xae]
+csetm   lr, hs
+
+# CHECK: csinc   lr, r10, r7, le  @ encoding: [0x5a,0xea,0xd7,0x9e]
+# CHECK-NOFP: csinc   lr, r10, r7, le  @ encoding: [0x5a,0xea,0xd7,0x9e]
+csinc   lr, r10, r7, le
+
+# CHECK: csinv   lr, r5, zr, hs  @ encoding: [0x55,0xea,0x2f,0xae]
+# CHECK-NOFP: csinv   lr, r5, zr, hs  @ encoding: [0x55,0xea,0x2f,0xae]
+csinv   lr, r5, zr, hs
+
+# CHECK: cinv    lr, r2, pl  @ encoding: [0x52,0xea,0x42,0xae]
+# CHECK-NOFP: cinv    lr, r2, pl  @ encoding: [0x52,0xea,0x42,0xae]
+csinv   lr, r2, r2, mi
+
+# CHECK: csneg   lr, r1, r11, vc  @ encoding: [0x51,0xea,0x7b,0xbe]
+# CHECK-NOFP: csneg   lr, r1, r11, vc  @ encoding: [0x51,0xea,0x7b,0xbe]
+csneg   lr, r1, r11, vc
+
+# CHECK: lsll    lr, r1, #11  @ encoding: [0x5e,0xea,0xcf,0x21]
+# CHECK-NOFP: lsll    lr, r1, #11  @ encoding: [0x5e,0xea,0xcf,0x21]
+lsll    lr, r1, #11
+
+# CHECK: lsll    lr, r1, r4  @ encoding: [0x5e,0xea,0x0d,0x41]
+# CHECK-NOFP: lsll    lr, r1, r4  @ encoding: [0x5e,0xea,0x0d,0x41]
+lsll    lr, r1, r4
+
+# CHECK: lsrl    lr, r1, #12  @ encoding: [0x5e,0xea,0x1f,0x31]
+# CHECK-NOFP: lsrl    lr, r1, #12  @ encoding: [0x5e,0xea,0x1f,0x31]
+lsrl    lr, r1, #12
+
+# CHECK: sqrshr  lr, r12  @ encoding: [0x5e,0xea,0x2d,0xcf]
+# CHECK-NOFP: sqrshr  lr, r12  @ encoding: [0x5e,0xea,0x2d,0xcf]
+sqrshr  lr, r12
+
+# CHECK: sqrshr  r11, r12  @ encoding: [0x5b,0xea,0x2d,0xcf]
+# CHECK-NOFP: sqrshr  r11, r12  @ encoding: [0x5b,0xea,0x2d,0xcf]
+sqrshr  r11, r12
+
+# CHECK: sqrshrl lr, r3, r8  @ encoding: [0x5f,0xea,0x2d,0x83]
+# CHECK-NOFP: sqrshrl lr, r3, r8  @ encoding: [0x5f,0xea,0x2d,0x83]
+sqrshrl lr, r3, r8
+
+# CHECK: sqshl   lr, #17  @ encoding: [0x5e,0xea,0x7f,0x4f]
+# CHECK-NOFP: sqshl   lr, #17  @ encoding: [0x5e,0xea,0x7f,0x4f]
+sqshl   lr, #17
+
+# CHECK: sqshll  lr, r11, #28  @ encoding: [0x5f,0xea,0x3f,0x7b]
+# CHECK-NOFP: sqshll  lr, r11, #28  @ encoding: [0x5f,0xea,0x3f,0x7b]
+sqshll  lr, r11, #28
+
+# CHECK: srshr   lr, #11  @ encoding: [0x5e,0xea,0xef,0x2f]
+# CHECK-NOFP: srshr   lr, #11  @ encoding: [0x5e,0xea,0xef,0x2f]
+srshr   lr, #11
+
+# CHECK: srshrl  lr, r11, #23  @ encoding: [0x5f,0xea,0xef,0x5b]
+# CHECK-NOFP: srshrl  lr, r11, #23  @ encoding: [0x5f,0xea,0xef,0x5b]
+srshrl  lr, r11, #23
+
+# CHECK: uqrshl  lr, r1  @ encoding: [0x5e,0xea,0x0d,0x1f]
+# CHECK-NOFP: uqrshl  lr, r1  @ encoding: [0x5e,0xea,0x0d,0x1f]
+uqrshl  lr, r1
+
+# CHECK: uqrshll lr, r1, r4  @ encoding: [0x5f,0xea,0x0d,0x41]
+# CHECK-NOFP: uqrshll lr, r1, r4  @ encoding: [0x5f,0xea,0x0d,0x41]
+uqrshll lr, r1, r4
+
+# CHECK: uqshl   r0, #1  @ encoding: [0x50,0xea,0x4f,0x0f]
+# CHECK-NOFP: uqshl   r0, #1  @ encoding: [0x50,0xea,0x4f,0x0f]
+uqshl   r0, #1
+
+# CHECK: uqshll  lr, r7, #7  @ encoding: [0x5f,0xea,0xcf,0x17]
+# CHECK-NOFP: uqshll  lr, r7, #7  @ encoding: [0x5f,0xea,0xcf,0x17]
+uqshll  lr, r7, #7
+
+# CHECK: urshr   r0, #10  @ encoding: [0x50,0xea,0x9f,0x2f]
+# CHECK-NOFP: urshr   r0, #10  @ encoding: [0x50,0xea,0x9f,0x2f]
+urshr   r0, #10
+
+# CHECK: urshrl  r0, r9, #29  @ encoding: [0x51,0xea,0x5f,0x79]
+# CHECK-NOFP: urshrl  r0, r9, #29  @ encoding: [0x51,0xea,0x5f,0x79]
+urshrl  r0, r9, #29
diff --git a/llvm/test/MC/Disassembler/ARM/mve-scalar-shift.txt b/llvm/test/MC/Disassembler/ARM/mve-scalar-shift.txt
new file mode 100644
--- /dev/null
+++ b/llvm/test/MC/Disassembler/ARM/mve-scalar-shift.txt
@@ -0,0 +1,83 @@
+# RUN: llvm-mc -disassemble -triple=thumbv8.1m.main-none-eabi -mattr=+mve.fp,+fp64 -show-encoding %s | FileCheck %s
+# RUN: not llvm-mc -disassemble -triple=thumbv8.1m.main-none-eabi -show-encoding %s &> %t
+# RUN: FileCheck --check-prefix=CHECK-NOMVE < %t %s
+
+[0x50 0xea 0xef 0x51]
+# CHECK: asrl r0, r1, #23 @ encoding: [0x50,0xea,0xef,0x51]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction 
+
+[0x5e 0xea 0xef 0x61]
+# CHECK: asrl lr, r1, #27 @ encoding: [0x5e,0xea,0xef,0x61]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x50 0xea 0x2d 0x41]
+# CHECK: asrl r0, r1, r4 @ encoding: [0x50,0xea,0x2d,0x41]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x5e 0xea 0xcf 0x21]
+# CHECK: lsll    lr, r1, #11  @ encoding: [0x5e,0xea,0xcf,0x21]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x5e 0xea 0x0d 0x41]
+# CHECK: lsll    lr, r1, r4  @ encoding: [0x5e,0xea,0x0d,0x41]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x5e 0xea 0x1f 0x31]
+# CHECK: lsrl    lr, r1, #12  @ encoding: [0x5e,0xea,0x1f,0x31]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x5f 0xea 0x2d 0x83]
+# CHECK: sqrshrl lr, r3, r8  @ encoding: [0x5f,0xea,0x2d,0x83]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x5e 0xea 0x7f 0x4f]
+# CHECK: sqshl   lr, #17  @ encoding: [0x5e,0xea,0x7f,0x4f]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x5f 0xea 0x3f 0x7b]
+# CHECK: sqshll  lr, r11, #28  @ encoding: [0x5f,0xea,0x3f,0x7b]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x5e 0xea 0xef 0x2f]
+# CHECK: srshr   lr, #11  @ encoding: [0x5e,0xea,0xef,0x2f]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x5f 0xea 0xef 0x5b]
+# CHECK: srshrl  lr, r11, #23  @ encoding: [0x5f,0xea,0xef,0x5b]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x5e 0xea 0x2d 0xcf]
+# CHECK: sqrshr  lr, r12  @ encoding: [0x5e,0xea,0x2d,0xcf]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x5b 0xea 0x2d 0xcf]
+# CHECK: sqrshr  r11, r12  @ encoding: [0x5b,0xea,0x2d,0xcf]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x5e 0xea 0x0d 0xcf]
+# CHECK: uqrshl  lr, r12  @ encoding: [0x5e,0xea,0x0d,0xcf]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x5b 0xea 0x0d 0xcf]
+# CHECK: uqrshl  r11, r12  @ encoding: [0x5b,0xea,0x0d,0xcf]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: invalid instruction encoding
+
+[0x5f 0xea 0x0d 0x41]
+# CHECK: uqrshll lr, r1, r4  @ encoding: [0x5f,0xea,0x0d,0x41]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x50 0xea 0x4f 0x0f]
+# CHECK: uqshl   r0, #1  @ encoding: [0x50,0xea,0x4f,0x0f]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x5f 0xea 0xcf 0x17]
+# CHECK: uqshll  lr, r7, #7  @ encoding: [0x5f,0xea,0xcf,0x17]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x50 0xea 0x9f 0x2f]
+# CHECK: urshr   r0, #10  @ encoding: [0x50,0xea,0x9f,0x2f]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding
+
+[0x51 0xea 0x5f 0x79]
+# CHECK: urshrl  r0, r9, #29  @ encoding: [0x51,0xea,0x5f,0x79]
+# CHECK-NOMVE: [[@LINE-2]]:2: warning: potentially undefined instruction encoding