[mips] Add range checks and transformation to octeon instructions in AsmParser.
authorKai Nacke <kai.nacke@redstar.de>
Tue, 27 Jan 2015 19:11:28 +0000 (19:11 +0000)
committerKai Nacke <kai.nacke@redstar.de>
Tue, 27 Jan 2015 19:11:28 +0000 (19:11 +0000)
This patch adds range checks to the immediate operands of octeon
instructions in the AsmParser. Like gas, it applies the following
transformations if the immediate is to large:

bbit0 $8, 42, foo => bbit032 $8, 10, foo
bbit1 $8, 46, foo => bbit132 $8, 14, foo
cins $8, $31, 32, 31 => cins32 $8, $31, 0, 31
exts $7, $4, 54, 9 => exts32 $7, $4, 22, 9

Reviewed By: dsanders

Differential Revision: http://reviews.llvm.org/D7080

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

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
test/MC/Mips/octeon-instructions.s

index 2e572c124dceadb1659222ab8473e2ab89da5c50..2e698dfbc9834f20485243cce702a8f7b788e169 100644 (file)
@@ -382,6 +382,9 @@ public:
   bool hasMips64r6() const {
     return (STI.getFeatureBits() & Mips::FeatureMips64r6);
   }
+  bool hasCnMips() const {
+    return (STI.getFeatureBits() & Mips::FeatureCnMips);
+  }
   bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); }
   bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); }
   bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); }
@@ -1168,6 +1171,13 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
     switch (Opcode) {
     default:
       break;
+    case Mips::BBIT0:
+    case Mips::BBIT032:
+    case Mips::BBIT1:
+    case Mips::BBIT132:
+      assert(hasCnMips() && "instruction only valid for octeon cpus");
+      // Fall through
+
     case Mips::BEQ:
     case Mips::BNE:
     case Mips::BEQ_MM:
@@ -1230,6 +1240,74 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
                                                       "nop instruction");
   }
 
+  if (hasCnMips()) {
+    const unsigned Opcode = Inst.getOpcode();
+    MCOperand Opnd;
+    int Imm;
+
+    switch (Opcode) {
+      default:
+        break;
+
+      case Mips::BBIT0:
+      case Mips::BBIT032:
+      case Mips::BBIT1:
+      case Mips::BBIT132:
+        assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
+        // The offset is handled above
+        Opnd = Inst.getOperand(1);
+        if (!Opnd.isImm())
+          return Error(IDLoc, "expected immediate operand kind");
+        Imm = Opnd.getImm();
+        if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 ||
+                              Opcode == Mips::BBIT1 ? 63 : 31))
+          return Error(IDLoc, "immediate operand value out of range");
+        if (Imm > 31) {
+          Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032
+                                               : Mips::BBIT132);
+          Inst.getOperand(1).setImm(Imm - 32);
+        }
+        break;
+
+      case Mips::CINS:
+      case Mips::CINS32:
+      case Mips::EXTS:
+      case Mips::EXTS32:
+        assert(MCID.getNumOperands() == 4 && "unexpected number of operands");
+        // Check length
+        Opnd = Inst.getOperand(3);
+        if (!Opnd.isImm())
+          return Error(IDLoc, "expected immediate operand kind");
+        Imm = Opnd.getImm();
+        if (Imm < 0 || Imm > 31)
+          return Error(IDLoc, "immediate operand value out of range");
+        // Check position
+        Opnd = Inst.getOperand(2);
+        if (!Opnd.isImm())
+          return Error(IDLoc, "expected immediate operand kind");
+        Imm = Opnd.getImm();
+        if (Imm < 0 || Imm > (Opcode == Mips::CINS ||
+                              Opcode == Mips::EXTS ? 63 : 31))
+          return Error(IDLoc, "immediate operand value out of range");
+        if (Imm > 31) {
+          Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32);
+          Inst.getOperand(2).setImm(Imm - 32);
+        }
+        break;
+
+      case Mips::SEQi:
+      case Mips::SNEi:
+        assert(MCID.getNumOperands() == 3 && "unexpected number of operands");
+        Opnd = Inst.getOperand(2);
+        if (!Opnd.isImm())
+          return Error(IDLoc, "expected immediate operand kind");
+        Imm = Opnd.getImm();
+        if (!isInt<10>(Imm))
+          return Error(IDLoc, "immediate operand value out of range");
+        break;
+    }
+  }
+
   if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
     // If this instruction has a delay slot and .set reorder is active,
     // emit a NOP after it.
index e98bbe40f68b71a4640470a14e8830ca3e1ebc05..34830c0fc6eb29ae2a8a102aa6d31ca608fb9a49 100644 (file)
@@ -5,12 +5,16 @@
 # CHECK: baddu $2, $2, $3             # encoding: [0x70,0x43,0x10,0x28]
 # CHECK: bbit0 $19, 22, foo           # encoding: [0xca,0x76,A,A]
 # CHECK: bbit032 $fp, 11, foo         # encoding: [0xdb,0xcb,A,A]
+# CHECK: bbit032 $8, 10, foo          # encoding: [0xd9,0x0a,A,A]
 # CHECK: bbit1 $3, 31, foo            # encoding: [0xe8,0x7f,A,A]
 # CHECK: bbit132 $24, 10, foo         # encoding: [0xfb,0x0a,A,A]
+# CHECK: bbit132 $14, 14, foo         # encoding: [0xf9,0xce,A,A]
 # CHECK: cins  $25, $10, 22, 2        # encoding: [0x71,0x59,0x15,0xb2]
 # CHECK: cins  $9, $9, 17, 29         # encoding: [0x71,0x29,0xec,0x72]
 # CHECK: cins32 $15, $2, 18, 8        # encoding: [0x70,0x4f,0x44,0xb3]
 # CHECK: cins32 $22, $22, 9, 22       # encoding: [0x72,0xd6,0xb2,0x73]
+# CHECK: cins32 $24, $ra, 0, 31       # encoding: [0x73,0xf8,0xf8,0x33]
+# CHECK: cins32 $15, $15, 5, 5        # encoding: [0x71,0xef,0x29,0x73]
 # CHECK: dmul  $9, $6, $7             # encoding: [0x70,0xc7,0x48,0x03]
 # CHECK: dmul  $19, $24, $25          # encoding: [0x73,0x19,0x98,0x03]
 # CHECK: dmul  $9, $9, $6             # encoding: [0x71,0x26,0x48,0x03]
@@ -22,6 +26,8 @@
 # CHECK: exts  $15, $15, 17, 6        # encoding: [0x71,0xef,0x34,0x7a]
 # CHECK: exts32 $4, $13, 10, 8        # encoding: [0x71,0xa4,0x42,0xbb]
 # CHECK: exts32 $15, $15, 11, 20      # encoding: [0x71,0xef,0xa2,0xfb]
+# CHECK: exts32 $7, $4, 22, 9         # encoding: [0x70,0x87,0x4d,0xbb]
+# CHECK: exts32 $25, $25, 5, 25       # encoding: [0x73,0x39,0xc9,0x7b]
 # CHECK: mtm0  $15                    # encoding: [0x71,0xe0,0x00,0x08]
 # CHECK: mtm1  $16                    # encoding: [0x72,0x00,0x00,0x0c]
 # CHECK: mtm2  $17                    # encoding: [0x72,0x20,0x00,0x0d]
@@ -56,12 +62,16 @@ foo:
   baddu $2, $3
   bbit0 $19, 22, foo
   bbit032 $30, 11, foo
+  bbit0 $8, 42, foo
   bbit1 $3, 31, foo
   bbit132 $24, 10, foo
+  bbit1 $14, 46, foo
   cins  $25, $10, 22, 2
   cins  $9, 17, 29
   cins32 $15, $2, 18, 8
   cins32 $22, 9, 22
+  cins  $24, $31, 32, 31
+  cins  $15, 37, 5
   dmul  $9, $6, $7
   dmul  $19, $24, $25
   dmul  $9, $6
@@ -73,6 +83,8 @@ foo:
   exts  $15, 17, 6
   exts32 $4, $13, 10, 8
   exts32 $15, 11, 20
+  exts  $7, $4, 54, 9
+  exts  $25, 37, 25
   mtm0  $15
   mtm1  $16
   mtm2  $17