[VE] Support fixed-point operation instructions in MC layer
authorKazushi (Jam) Marukawa <marukawa@nec.com>
Fri, 5 Jun 2020 09:55:47 +0000 (11:55 +0200)
committerSimon Moll <simon.moll@emea.nec.com>
Fri, 5 Jun 2020 09:56:26 +0000 (11:56 +0200)
Summary:
Add regression tests of asmparser, mccodeemitter, and disassembler for
fixed-point operation instructions.  In order to support them, we add
MImm parser to asmparser.  Also add a new MPD instruction which is one
of multiply instructions.

Differential Revision: https://reviews.llvm.org/D81207

llvm/lib/Target/VE/AsmParser/VEAsmParser.cpp
llvm/lib/Target/VE/VEInstrInfo.td
llvm/test/MC/VE/ADD.s [new file with mode: 0644]
llvm/test/MC/VE/CMP.s [new file with mode: 0644]
llvm/test/MC/VE/DIV.s [new file with mode: 0644]
llvm/test/MC/VE/MAXMIN.s [new file with mode: 0644]
llvm/test/MC/VE/MUL.s [new file with mode: 0644]
llvm/test/MC/VE/SUB.s [new file with mode: 0644]

index 30dd581..b2d3831 100644 (file)
@@ -67,6 +67,7 @@ class VEAsmParser : public MCTargetAsmParser {
 
   // Custom parse functions for VE specific operands.
   OperandMatchResultTy parseMEMOperand(OperandVector &Operands);
+  OperandMatchResultTy parseMImmOperand(OperandVector &Operands);
   OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name);
   OperandMatchResultTy parseVEAsmOperand(std::unique_ptr<VEOperand> &Operand);
 
@@ -120,6 +121,8 @@ private:
     k_MemoryRegImmImm,  // base=reg, index=imm, disp=imm
     k_MemoryZeroRegImm, // base=0, index=reg, disp=imm
     k_MemoryZeroImmImm, // base=0, index=imm, disp=imm
+    k_MImmOp,           // Special immediate value of sequential bit stream
+                        // of 0 or 1.
   } Kind;
 
   SMLoc StartLoc, EndLoc;
@@ -144,11 +147,17 @@ private:
     const MCExpr *Offset;
   };
 
+  struct MImmOp {
+    const MCExpr *Val;
+    bool M0Flag;
+  };
+
   union {
     struct Token Tok;
     struct RegOp Reg;
     struct ImmOp Imm;
     struct MemOp Mem;
+    struct MImmOp MImm;
   };
 
 public:
@@ -179,6 +188,17 @@ public:
     }
     return false;
   }
+  bool isMImm() const {
+    if (Kind != k_MImmOp)
+      return false;
+
+    // Constant case
+    if (const MCConstantExpr *ConstExpr = dyn_cast<MCConstantExpr>(MImm.Val)) {
+      int64_t Value = ConstExpr->getValue();
+      return isUInt<6>(Value);
+    }
+    return false;
+  }
 
   StringRef getToken() const {
     assert(Kind == k_Token && "Invalid access!");
@@ -227,6 +247,15 @@ public:
     Mem.Offset = off;
   }
 
+  const MCExpr *getMImmVal() const {
+    assert((Kind == k_MImmOp) && "Invalid access!");
+    return MImm.Val;
+  }
+  bool getM0Flag() const {
+    assert((Kind == k_MImmOp) && "Invalid access!");
+    return MImm.M0Flag;
+  }
+
   /// getStartLoc - Get the location of the first token of this operand.
   SMLoc getStartLoc() const override { return StartLoc; }
   /// getEndLoc - Get the location of the last token of this operand.
@@ -261,6 +290,9 @@ public:
       assert(getMemIndex() != nullptr && getMemOffset() != nullptr);
       OS << "Mem: 0+" << *getMemIndex() << "+" << *getMemOffset() << "\n";
       break;
+    case k_MImmOp:
+      OS << "MImm: (" << getMImmVal() << (getM0Flag() ? ")0" : ")1") << "\n";
+      break;
     }
   }
 
@@ -329,6 +361,16 @@ public:
     // FIXME: implement
   }
 
+  void addMImmOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    const auto *ConstExpr = dyn_cast<MCConstantExpr>(getMImmVal());
+    assert(ConstExpr && "Null operands!");
+    int64_t Value = ConstExpr->getValue();
+    if (getM0Flag())
+      Value += 64;
+    Inst.addOperand(MCOperand::createImm(Value));
+  }
+
   static std::unique_ptr<VEOperand> CreateToken(StringRef Str, SMLoc S) {
     auto Op = std::make_unique<VEOperand>(k_Token);
     Op->Tok.Data = Str.data();
@@ -356,6 +398,16 @@ public:
     return Op;
   }
 
+  static std::unique_ptr<VEOperand> CreateMImm(const MCExpr *Val, bool Flag,
+                                               SMLoc S, SMLoc E) {
+    auto Op = std::make_unique<VEOperand>(k_MImmOp);
+    Op->MImm.Val = Val;
+    Op->MImm.M0Flag = Flag;
+    Op->StartLoc = S;
+    Op->EndLoc = E;
+    return Op;
+  }
+
   static bool MorphToI32Reg(VEOperand &Op) {
     unsigned Reg = Op.getReg();
     unsigned regIdx = Reg - VE::SX0;
@@ -651,6 +703,47 @@ OperandMatchResultTy VEAsmParser::parseMEMOperand(OperandVector &Operands) {
   return MatchOperand_Success;
 }
 
+OperandMatchResultTy VEAsmParser::parseMImmOperand(OperandVector &Operands) {
+  LLVM_DEBUG(dbgs() << "parseMImmOperand\n");
+
+  // Parsing "(" + number + ")0/1"
+  const AsmToken Tok1 = Parser.getTok();
+  if (!Tok1.is(AsmToken::LParen))
+    return MatchOperand_NoMatch;
+
+  Parser.Lex(); // Eat the '('.
+
+  const AsmToken Tok2 = Parser.getTok();
+  SMLoc E;
+  const MCExpr *EVal;
+  if (!Tok2.is(AsmToken::Integer) || getParser().parseExpression(EVal, E)) {
+    getLexer().UnLex(Tok1);
+    return MatchOperand_NoMatch;
+  }
+
+  const AsmToken Tok3 = Parser.getTok();
+  if (!Tok3.is(AsmToken::RParen)) {
+    getLexer().UnLex(Tok2);
+    getLexer().UnLex(Tok1);
+    return MatchOperand_NoMatch;
+  }
+  Parser.Lex(); // Eat the ')'.
+
+  const AsmToken &Tok4 = Parser.getTok();
+  StringRef Suffix = Tok4.getString();
+  if (Suffix != "1" && Suffix != "0") {
+    getLexer().UnLex(Tok3);
+    getLexer().UnLex(Tok2);
+    getLexer().UnLex(Tok1);
+    return MatchOperand_NoMatch;
+  }
+  Parser.Lex(); // Eat the value.
+  SMLoc EndLoc = SMLoc::getFromPointer(Suffix.end());
+  Operands.push_back(
+      VEOperand::CreateMImm(EVal, Suffix == "0", Tok1.getLoc(), EndLoc));
+  return MatchOperand_Success;
+}
+
 OperandMatchResultTy VEAsmParser::parseOperand(OperandVector &Operands,
                                                StringRef Mnemonic) {
   LLVM_DEBUG(dbgs() << "parseOperand\n");
index 89be9bd..27eb11c 100644 (file)
@@ -116,14 +116,23 @@ def uimm7 : Operand<i32>, PatLeaf<(imm), [{
     return isUInt<7>(N->getZExtValue()); }]>;
 
 // simm7 - Generic immediate value.
+def SImm7AsmOperand : AsmOperandClass {
+  let Name = "SImm7";
+}
 def simm7 : Operand<i32>, PatLeaf<(imm), [{
     return isInt<7>(N->getSExtValue()); }], LO7> {
+  let ParserMatchClass = SImm7AsmOperand;
   let DecoderMethod = "DecodeSIMM7";
 }
 
 // mimm - Special immediate value of sequential bit stream of 0 or 1.
+def MImmAsmOperand : AsmOperandClass {
+  let Name = "MImm";
+  let ParserMethod = "parseMImmOperand";
+}
 def mimm : Operand<i32>, PatLeaf<(imm), [{
     return isMImmVal(getImmVal(N)); }], MIMM> {
+  let ParserMatchClass = MImmAsmOperand;
   let PrintMethod = "printMImmOperand";
 }
 
@@ -817,6 +826,7 @@ let cx = 1 in defm MULSWZX : RRm<"muls.w.zx", 0x4B, I32, i32>;
 defm MULSL : RRm<"muls.l", 0x6E, I64, i64, mul>;
 
 // Section 8.4.10 - MPD (Multiply)
+defm MULSLW : RRbm<"muls.l.w", 0x6B, I64, i64, I32, i32>;
 
 // Section 8.4.11 - DIV (Divide)
 defm DIVUL : RRNCm<"divu.l", 0x6F, I64, i64, udiv>;
diff --git a/llvm/test/MC/VE/ADD.s b/llvm/test/MC/VE/ADD.s
new file mode 100644 (file)
index 0000000..9cdc97e
--- /dev/null
@@ -0,0 +1,24 @@
+# RUN: llvm-mc -triple=ve --show-encoding < %s \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-INST
+
+# CHECK-INST: addu.l %s11, %s20, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x94,0x0b,0x48]
+addu.l %s11, %s20, %s22
+
+# CHECK-INST: addu.w %s11, 22, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x16,0x8b,0x48]
+addu.w %s11, 22, %s22
+
+# CHECK-INST: adds.w.sx %s11, 63, (60)1
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x3c,0x3f,0x0b,0x4a]
+adds.w.sx %s11, 63, (60)1
+
+# CHECK-INST: adds.w.zx %s11, -64, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x40,0x8b,0x4a]
+adds.w.zx %s11, -64, %s22
+
+# CHECK-INST: adds.l %s11, -64, (22)0
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x56,0x40,0x0b,0x59]
+adds.l %s11, -64, (22)0
diff --git a/llvm/test/MC/VE/CMP.s b/llvm/test/MC/VE/CMP.s
new file mode 100644 (file)
index 0000000..c2e3af8
--- /dev/null
@@ -0,0 +1,24 @@
+# RUN: llvm-mc -triple=ve --show-encoding < %s \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-INST
+
+# CHECK-INST: cmpu.l %s11, %s20, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x94,0x0b,0x55]
+cmpu.l %s11, %s20, %s22
+
+# CHECK-INST: cmpu.w %s11, 22, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x16,0x8b,0x55]
+cmpu.w %s11, 22, %s22
+
+# CHECK-INST: cmps.w.sx %s11, 63, (60)1
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x3c,0x3f,0x0b,0x7a]
+cmps.w.sx %s11, 63, (60)1
+
+# CHECK-INST: cmps.w.zx %s11, -64, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x40,0x8b,0x7a]
+cmps.w.zx %s11, -64, %s22
+
+# CHECK-INST: cmps.l %s11, -64, (22)0
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x56,0x40,0x0b,0x6a]
+cmps.l %s11, -64, (22)0
diff --git a/llvm/test/MC/VE/DIV.s b/llvm/test/MC/VE/DIV.s
new file mode 100644 (file)
index 0000000..a81718c
--- /dev/null
@@ -0,0 +1,24 @@
+# RUN: llvm-mc -triple=ve --show-encoding < %s \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-INST
+
+# CHECK-INST: divu.l %s11, %s20, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x94,0x0b,0x6f]
+divu.l %s11, %s20, %s22
+
+# CHECK-INST: divu.w %s11, 22, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x16,0x8b,0x6f]
+divu.w %s11, 22, %s22
+
+# CHECK-INST: divs.w.sx %s11, 63, (60)1
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x3c,0x3f,0x0b,0x7b]
+divs.w.sx %s11, 63, (60)1
+
+# CHECK-INST: divs.w.zx %s11, -64, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x40,0x8b,0x7b]
+divs.w.zx %s11, -64, %s22
+
+# CHECK-INST: divs.l %s11, -64, (22)0
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x56,0x40,0x0b,0x7f]
+divs.l %s11, -64, (22)0
diff --git a/llvm/test/MC/VE/MAXMIN.s b/llvm/test/MC/VE/MAXMIN.s
new file mode 100644 (file)
index 0000000..5ccb606
--- /dev/null
@@ -0,0 +1,28 @@
+# RUN: llvm-mc -triple=ve --show-encoding < %s \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-INST
+
+# CHECK-INST: maxs.w.sx %s11, %s20, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x94,0x0b,0x78]
+maxs.w.sx %s11, %s20, %s22
+
+# CHECK-INST: maxs.w.zx %s11, 22, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x16,0x8b,0x78]
+maxs.w.zx %s11, 22, %s22
+
+# CHECK-INST: mins.w.sx %s11, 63, (63)1
+# CHECK-ENCODING: encoding: [0x80,0x00,0x00,0x00,0x3f,0x3f,0x0b,0x78]
+mins.w.sx %s11, 63, (63)1
+
+# CHECK-INST: mins.w.zx %s11, -64, %s22
+# CHECK-ENCODING: encoding: [0x80,0x00,0x00,0x00,0x96,0x40,0x8b,0x78]
+mins.w.zx %s11, -64, %s22
+
+# CHECK-INST: maxs.l %s11, -64, (22)0
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x56,0x40,0x0b,0x68]
+maxs.l %s11, -64, (22)0
+
+# CHECK-INST: mins.l %s11, -64, (22)1
+# CHECK-ENCODING: encoding: [0x80,0x00,0x00,0x00,0x16,0x40,0x0b,0x68]
+mins.l %s11, -64, (22)1
diff --git a/llvm/test/MC/VE/MUL.s b/llvm/test/MC/VE/MUL.s
new file mode 100644 (file)
index 0000000..632562c
--- /dev/null
@@ -0,0 +1,28 @@
+# RUN: llvm-mc -triple=ve --show-encoding < %s \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-INST
+
+# CHECK-INST: mulu.l %s11, %s20, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x94,0x0b,0x49]
+mulu.l %s11, %s20, %s22
+
+# CHECK-INST: mulu.w %s11, 22, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x16,0x8b,0x49]
+mulu.w %s11, 22, %s22
+
+# CHECK-INST: muls.w.sx %s11, 63, (60)1
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x3c,0x3f,0x0b,0x4b]
+muls.w.sx %s11, 63, (60)1
+
+# CHECK-INST: muls.w.zx %s11, -64, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x40,0x8b,0x4b]
+muls.w.zx %s11, -64, %s22
+
+# CHECK-INST: muls.l %s11, -64, (22)0
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x56,0x40,0x0b,0x6e]
+muls.l %s11, -64, (22)0
+
+# CHECK-INST: muls.l.w %s11, -64, (22)0
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x56,0x40,0x0b,0x6b]
+muls.l.w %s11, -64, (22)0
diff --git a/llvm/test/MC/VE/SUB.s b/llvm/test/MC/VE/SUB.s
new file mode 100644 (file)
index 0000000..c73f238
--- /dev/null
@@ -0,0 +1,24 @@
+# RUN: llvm-mc -triple=ve --show-encoding < %s \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \
+# RUN:     | FileCheck %s --check-prefixes=CHECK-INST
+
+# CHECK-INST: subu.l %s11, %s20, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x94,0x0b,0x58]
+subu.l %s11, %s20, %s22
+
+# CHECK-INST: subu.w %s11, 22, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x16,0x8b,0x58]
+subu.w %s11, 22, %s22
+
+# CHECK-INST: subs.w.sx %s11, 63, (60)1
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x3c,0x3f,0x0b,0x5a]
+subs.w.sx %s11, 63, (60)1
+
+# CHECK-INST: subs.w.zx %s11, -64, %s22
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x96,0x40,0x8b,0x5a]
+subs.w.zx %s11, -64, %s22
+
+# CHECK-INST: subs.l %s11, -64, (22)0
+# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x56,0x40,0x0b,0x5b]
+subs.l %s11, -64, (22)0