Split up the ARM so_reg ComplexPattern into so_reg_reg and so_reg_imm, allowing us to distinguish the encodings that use shifted registers from those that use shifted immediates.  This is necessary to allow the fixed-length decoder to distinguish things like BICS vs LDRH.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135693 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 3232c5d..ed5235f 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -172,6 +172,7 @@
     DPRRegisterList,
     SPRRegisterList,
     ShiftedRegister,
+    ShiftedImmediate,
     Shifter,
     Token
   } Kind;
@@ -241,6 +242,11 @@
       unsigned ShiftReg;
       unsigned ShiftImm;
     } ShiftedReg;
+    struct {
+      ARM_AM::ShiftOpc ShiftTy;
+      unsigned SrcReg;
+      unsigned ShiftImm;
+    } ShiftedImm;
   };
 
   ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
@@ -290,6 +296,9 @@
     case ShiftedRegister:
       ShiftedReg = o.ShiftedReg;
       break;
+    case ShiftedImmediate:
+      ShiftedImm = o.ShiftedImm;
+      break;
     }
   }
 
@@ -468,6 +477,7 @@
   bool isMemory() const { return Kind == Memory; }
   bool isShifter() const { return Kind == Shifter; }
   bool isShiftedReg() const { return Kind == ShiftedRegister; }
+  bool isShiftedImm() const { return Kind == ShiftedImmediate; }
   bool isMemMode2() const {
     if (getMemAddrMode() != ARMII::AddrMode2)
       return false;
@@ -601,15 +611,25 @@
   void addShiftedRegOperands(MCInst &Inst, unsigned N) const {
     assert(N == 3 && "Invalid number of operands!");
     assert(isShiftedReg() && "addShiftedRegOperands() on non ShiftedReg!");
-    assert((ShiftedReg.ShiftReg == 0 ||
-            ARM_AM::getSORegOffset(ShiftedReg.ShiftImm) == 0) &&
-           "Invalid shifted register operand!");
     Inst.addOperand(MCOperand::CreateReg(ShiftedReg.SrcReg));
     Inst.addOperand(MCOperand::CreateReg(ShiftedReg.ShiftReg));
     Inst.addOperand(MCOperand::CreateImm(
       ARM_AM::getSORegOpc(ShiftedReg.ShiftTy, ShiftedReg.ShiftImm)));
   }
 
+  void addShiftedImmOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 3 && "Invalid number of operands!");
+    assert(isShiftedImm() && "addShiftedImmOperands() on non ShiftedImm!");
+    Inst.addOperand(MCOperand::CreateReg(ShiftedImm.SrcReg));
+    if (ShiftedImm.ShiftTy == ARM_AM::rrx)
+      Inst.addOperand(MCOperand::CreateReg(ShiftedImm.SrcReg));
+    else
+      Inst.addOperand(MCOperand::CreateReg(0));
+    Inst.addOperand(MCOperand::CreateImm(
+      ARM_AM::getSORegOpc(ShiftedImm.ShiftTy, ShiftedImm.ShiftImm)));
+  }
+
+
   void addShifterOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     Inst.addOperand(MCOperand::CreateImm(
@@ -885,6 +905,19 @@
     return Op;
   }
 
+  static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
+                                            unsigned SrcReg,
+                                            unsigned ShiftImm,
+                                            SMLoc S, SMLoc E) {
+    ARMOperand *Op = new ARMOperand(ShiftedImmediate);
+    Op->ShiftedImm.ShiftTy = ShTy;
+    Op->ShiftedImm.SrcReg = SrcReg;
+    Op->ShiftedImm.ShiftImm = ShiftImm;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
+  }
+
   static ARMOperand *CreateShifter(ARM_AM::ShiftOpc ShTy,
                                    SMLoc S, SMLoc E) {
     ARMOperand *Op = new ARMOperand(Shifter);
@@ -1052,13 +1085,20 @@
     OS << "<shifter " << ARM_AM::getShiftOpcStr(Shift.ShiftTy) << ">";
     break;
   case ShiftedRegister:
-    OS << "<so_reg"
+    OS << "<so_reg_reg "
        << ShiftedReg.SrcReg
        << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(ShiftedReg.ShiftImm))
        << ", " << ShiftedReg.ShiftReg << ", "
        << ARM_AM::getSORegOffset(ShiftedReg.ShiftImm)
        << ">";
     break;
+  case ShiftedImmediate:
+    OS << "<so_reg_imm "
+       << ShiftedImm.SrcReg
+       << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(ShiftedImm.ShiftImm))
+       << ", " << ARM_AM::getSORegOffset(ShiftedImm.ShiftImm)
+       << ">";
+    break;
   case RegisterList:
   case DPRRegisterList:
   case SPRRegisterList: {
@@ -1201,9 +1241,13 @@
     }
   }
 
-  Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
+  if (ShiftReg && ShiftTy != ARM_AM::rrx)
+    Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
                                                        ShiftReg, Imm,
                                                S, Parser.getTok().getLoc()));
+  else
+    Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
+                                               S, Parser.getTok().getLoc()));
 
   return 0;
 }