ARM assembly parsing for MOV (register).
authorJim Grosbach <grosbach@apple.com>
Tue, 19 Jul 2011 20:10:31 +0000 (20:10 +0000)
committerJim Grosbach <grosbach@apple.com>
Tue, 19 Jul 2011 20:10:31 +0000 (20:10 +0000)
Correct the handling of the 's' suffix when parsing ARM mode. It's only a
truly separate opcode in Thumb. Add test cases to make sure we handle
the s and condition suffices correctly, including diagnostics.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135513 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/AsmParser/ARMAsmParser.cpp
test/MC/ARM/basic-arm-instructions.s
test/MC/ARM/diagnostics.s

index 4a0c388d91487577c1294da8245921a98f48c1b8..752e90af775bb07903ad4b2beba543b0d862f8d9 100644 (file)
@@ -79,6 +79,8 @@ class ARMAsmParser : public TargetAsmParser {
   bool MatchAndEmitInstruction(SMLoc IDLoc,
                                SmallVectorImpl<MCParsedAsmOperand*> &Operands,
                                MCStreamer &Out);
+  StringRef SplitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
+                          bool &CarrySetting, unsigned &ProcessorIMod);
   void GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
                              bool &CanAcceptPredicationCode);
 
@@ -1952,10 +1954,10 @@ ARMAsmParser::ApplyPrefixToExpr(const MCExpr *E,
 /// setting letters to form a canonical mnemonic and flags.
 //
 // FIXME: Would be nice to autogen this.
-static StringRef SplitMnemonic(StringRef Mnemonic,
-                               unsigned &PredicationCode,
-                               bool &CarrySetting,
-                               unsigned &ProcessorIMod) {
+StringRef ARMAsmParser::SplitMnemonic(StringRef Mnemonic,
+                                      unsigned &PredicationCode,
+                                      bool &CarrySetting,
+                                      unsigned &ProcessorIMod) {
   PredicationCode = ARMCC::AL;
   CarrySetting = false;
   ProcessorIMod = 0;
@@ -1963,19 +1965,19 @@ static StringRef SplitMnemonic(StringRef Mnemonic,
   // Ignore some mnemonics we know aren't predicated forms.
   //
   // FIXME: Would be nice to autogen this.
-  if (Mnemonic == "teq"   || Mnemonic == "vceq"  || Mnemonic == "movs"   ||
-      Mnemonic == "svc"   || Mnemonic == "mls"   || Mnemonic == "smmls"  ||
-      Mnemonic == "vcls"  || Mnemonic == "vmls"  || Mnemonic == "vnmls"  ||
-      Mnemonic == "vacge" || Mnemonic == "vcge"  || Mnemonic == "vclt"   ||
-      Mnemonic == "vacgt" || Mnemonic == "vcgt"  || Mnemonic == "vcle"   ||
-      Mnemonic == "smlal" || Mnemonic == "umaal" || Mnemonic == "umlal"  ||
-      Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" ||
-      Mnemonic == "vqdmlal")
+  if ((Mnemonic == "movs" && isThumb()) ||
+      Mnemonic == "teq"   || Mnemonic == "vceq"   || Mnemonic == "svc"   ||
+      Mnemonic == "mls"   || Mnemonic == "smmls"  || Mnemonic == "vcls"  ||
+      Mnemonic == "vmls"  || Mnemonic == "vnmls"  || Mnemonic == "vacge" ||
+      Mnemonic == "vcge"  || Mnemonic == "vclt"   || Mnemonic == "vacgt" ||
+      Mnemonic == "vcgt"  || Mnemonic == "vcle"   || Mnemonic == "smlal" ||
+      Mnemonic == "umaal" || Mnemonic == "umlal"  || Mnemonic == "vabal" ||
+      Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal")
     return Mnemonic;
 
   // First, split out any predication code. Ignore mnemonics we know aren't
   // predicated but do have a carry-set and so weren't caught above.
-  if (Mnemonic != "adcs" && Mnemonic != "bics") {
+  if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs") {
     unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
       .Case("eq", ARMCC::EQ)
       .Case("ne", ARMCC::NE)
@@ -2005,10 +2007,10 @@ static StringRef SplitMnemonic(StringRef Mnemonic,
   // the instructions we know end in 's'.
   if (Mnemonic.endswith("s") &&
       !(Mnemonic == "asrs" || Mnemonic == "cps" || Mnemonic == "mls" ||
-        Mnemonic == "movs" || Mnemonic == "mrs" || Mnemonic == "smmls" ||
-        Mnemonic == "vabs" || Mnemonic == "vcls" || Mnemonic == "vmls" ||
-        Mnemonic == "vmrs" || Mnemonic == "vnmls" || Mnemonic == "vqabs" ||
-        Mnemonic == "vrecps" || Mnemonic == "vrsqrts")) {
+        Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
+        Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
+        Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
+        Mnemonic == "vrsqrts" || (Mnemonic == "movs" && isThumb()))) {
     Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
     CarrySetting = true;
   }
@@ -2056,8 +2058,8 @@ GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
       Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
       Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
       Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
-      Mnemonic == "dsb" || Mnemonic == "movs" || Mnemonic == "isb" ||
-      Mnemonic == "clrex" || Mnemonic.startswith("cps")) {
+      Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "clrex" ||
+      Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumb())) {
     CanAcceptPredicationCode = false;
   } else {
     CanAcceptPredicationCode = true;
index f54723a4f529efdadc59b3fd1ac991d73b734991..3bc061127a43a48670523b7a6f6729f6de6a4de1 100644 (file)
@@ -678,12 +678,31 @@ _func:
     mov r5, #0xff0000
     mov r6, #0xffff
     movw r9, #0xffff
+    movs r3, #7
+    moveq r4, #0xff0
+    movseq r5, #0xff0000
 
 @ CHECK: mov   r3, #7                  @ encoding: [0x07,0x30,0xa0,0xe3]
 @ CHECK: mov   r4, #4080               @ encoding: [0xff,0x4e,0xa0,0xe3]
 @ CHECK: mov   r5, #16711680           @ encoding: [0xff,0x58,0xa0,0xe3]
 @ CHECK: movw  r6, #65535              @ encoding: [0xff,0x6f,0x0f,0xe3]
 @ CHECK: movw  r9, #65535              @ encoding: [0xff,0x9f,0x0f,0xe3]
+@ CHECK: movs  r3, #7                  @ encoding: [0x07,0x30,0xb0,0xe3]
+@ CHECK: moveq r4, #4080               @ encoding: [0xff,0x4e,0xa0,0x03]
+@ CHECK: movseq        r5, #16711680           @ encoding: [0xff,0x58,0xb0,0x03]
+
+@------------------------------------------------------------------------------
+@ MOV (register)
+@------------------------------------------------------------------------------
+        mov r2, r3
+        movs r2, r3
+        moveq r2, r3
+        movseq r2, r3
+
+@ CHECK: mov   r2, r3                  @ encoding: [0x03,0x20,0xa0,0xe1]
+@ CHECK: movs  r2, r3                  @ encoding: [0x03,0x20,0xb0,0xe1]
+@ CHECK: moveq r2, r3                  @ encoding: [0x03,0x20,0xa0,0x01]
+@ CHECK: movseq        r2, r3                  @ encoding: [0x03,0x20,0xb0,0x01]
 
 @------------------------------------------------------------------------------
 @ STM*
index 1ae41ebb6c990b9e6ea2a058810705a8405ccf18..08c982e182fcdc954b6ec8bc46596a915497ab70 100644 (file)
@@ -93,3 +93,9 @@
         @ Out of range immediate for MOV
         movw r9, 0x10000
 @ CHECK-ERRORS: error: invalid operand for instruction
+
+        @ Invalid 's' bit usage for MOVW
+        movs r6, #0xffff
+        movwseq r9, #0xffff
+@ CHECK-ERRORS: error: invalid operand for instruction
+@ CHECK-ERRORS: error: instruction 'movw' can not set flags, but 's' suffix specified