[CSKY 5/n] Add support for all CSKY basic integer instructions except for branch...
authorZi Xuan Wu <zixuan.wu@linux.alibaba.com>
Tue, 20 Apr 2021 06:40:46 +0000 (14:40 +0800)
committerZi Xuan Wu <zixuan.wu@linux.alibaba.com>
Tue, 20 Apr 2021 07:36:49 +0000 (15:36 +0800)
This patch adds basic CSKY integer instructions except for branch series such as bsr, br.
It mainly includes basic ALU, load & store, compare and data move instructions.

Branch series instructions need handle complex symbol operand as following patch later.

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

llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
llvm/lib/Target/CSKY/CSKYInstrFormats.td
llvm/lib/Target/CSKY/CSKYInstrInfo.td
llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h
llvm/test/MC/CSKY/basic.s

index 718b14c..c971638 100644 (file)
@@ -57,6 +57,7 @@ class CSKYAsmParser : public MCTargetAsmParser {
 
   OperandMatchResultTy parseImmediate(OperandVector &Operands);
   OperandMatchResultTy parseRegister(OperandVector &Operands);
+  OperandMatchResultTy parseBaseRegImm(OperandVector &Operands);
 
   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
 
@@ -132,13 +133,13 @@ public:
     return false;
   }
 
-  template <unsigned num> bool isUImm() const {
+  template <unsigned num, unsigned shift = 0> bool isUImm() const {
     if (!isImm())
       return false;
 
     int64_t Imm;
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
-    return IsConstantImm && isUInt<num>(Imm);
+    return IsConstantImm && isShiftedUInt<num, shift>(Imm);
   }
 
   template <unsigned num> bool isOImm() const {
@@ -150,18 +151,25 @@ public:
     return IsConstantImm && isUInt<num>(Imm - 1);
   }
 
-  template <unsigned num> bool isSImm() const {
+  template <unsigned num, unsigned shift = 0> bool isSImm() const {
     if (!isImm())
       return false;
 
     int64_t Imm;
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
-    return IsConstantImm && isInt<num>(Imm);
+    return IsConstantImm && isShiftedInt<num, shift>(Imm);
   }
 
+  bool isUImm2() const { return isUImm<2>(); }
   bool isUImm5() const { return isUImm<5>(); }
   bool isUImm12() const { return isUImm<12>(); }
+  bool isUImm16() const { return isUImm<16>(); }
+
   bool isOImm12() const { return isOImm<12>(); }
+  bool isOImm16() const { return isOImm<16>(); }
+
+  bool isUImm12Shift1() { return isUImm<12, 1>(); }
+  bool isUImm12Shift2() { return isUImm<12, 2>(); }
 
   /// Gets location of the first token of this operand.
   SMLoc getStartLoc() const override { return StartLoc; }
@@ -295,6 +303,7 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
         CSKYMnemonicSpellCheck(((CSKYOperand &)*Operands[0]).getToken(), FBS);
     return Error(IDLoc, "unrecognized instruction mnemonic" + Suggestion);
   }
+  case Match_InvalidTiedOperand:
   case Match_InvalidOperand: {
     SMLoc ErrorLoc = IDLoc;
     if (ErrorInfo != ~0U) {
@@ -323,10 +332,24 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     break;
   case Match_InvalidOImm12:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12));
-  case Match_InvalidUImm12:
-    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
+  case Match_InvalidOImm16:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 16));
+  case Match_InvalidUImm2:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
   case Match_InvalidUImm5:
     return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
+  case Match_InvalidUImm12:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
+  case Match_InvalidUImm12Shift1:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, 0, (1 << 12) - 2,
+        "immediate must be a multiple of 2 bytes in the range");
+  case Match_InvalidUImm12Shift2:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, 0, (1 << 12) - 4,
+        "immediate must be a multiple of 4 bytes in the range");
+  case Match_InvalidUImm16:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1);
   }
 
   llvm_unreachable("Unknown match type detected!");
@@ -381,6 +404,58 @@ OperandMatchResultTy CSKYAsmParser::parseRegister(OperandVector &Operands) {
   }
 }
 
+OperandMatchResultTy CSKYAsmParser::parseBaseRegImm(OperandVector &Operands) {
+  assert(getLexer().is(AsmToken::LParen));
+
+  Operands.push_back(CSKYOperand::createToken("(", getLoc()));
+
+  auto Tok = getParser().Lex(); // Eat '('
+
+  if (parseRegister(Operands) != MatchOperand_Success) {
+    getLexer().UnLex(Tok);
+    Operands.pop_back();
+    return MatchOperand_ParseFail;
+  }
+
+  if (getLexer().isNot(AsmToken::Comma)) {
+    Error(getLoc(), "expected ','");
+    return MatchOperand_ParseFail;
+  }
+
+  getParser().Lex(); // Eat ','
+
+  if (parseRegister(Operands) == MatchOperand_Success) {
+    if (getLexer().isNot(AsmToken::LessLess)) {
+      Error(getLoc(), "expected '<<'");
+      return MatchOperand_ParseFail;
+    }
+
+    Operands.push_back(CSKYOperand::createToken("<<", getLoc()));
+
+    getParser().Lex(); // Eat '<<'
+
+    if (parseImmediate(Operands) != MatchOperand_Success) {
+      Error(getLoc(), "expected imm");
+      return MatchOperand_ParseFail;
+    }
+
+  } else if (parseImmediate(Operands) != MatchOperand_Success) {
+    Error(getLoc(), "expected imm");
+    return MatchOperand_ParseFail;
+  }
+
+  if (getLexer().isNot(AsmToken::RParen)) {
+    Error(getLoc(), "expected ')'");
+    return MatchOperand_ParseFail;
+  }
+
+  Operands.push_back(CSKYOperand::createToken(")", getLoc()));
+
+  getParser().Lex(); // Eat ')'
+
+  return MatchOperand_Success;
+}
+
 OperandMatchResultTy CSKYAsmParser::parseImmediate(OperandVector &Operands) {
   switch (getLexer().getKind()) {
   default:
@@ -411,6 +486,11 @@ bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
   if (parseRegister(Operands) == MatchOperand_Success)
     return false;
 
+  // Attempt to parse token as (register, imm)
+  if (getLexer().is(AsmToken::LParen))
+    if (parseBaseRegImm(Operands) == MatchOperand_Success)
+      return false;
+
   // Attempt to parse token as a imm.
   if (parseImmediate(Operands) == MatchOperand_Success)
     return false;
index 86f9dd0..bc247ee 100644 (file)
@@ -58,8 +58,8 @@ class J<bits<6> opcode, dag outs, dag ins, string op, list<dag> pattern>
 
 // Format< OP[6] | RZ[5] | SOP[3] | OFFSET[18] >
 // Instructions(7): grs, lrs32.b, lrs32.h, lrs32.w, srs32.b, srs32.h, srs32.w
-class I_18_Z_L<bits<3> sop, string op, Operand operand, list<dag> pattern>
-    : CSKY32Inst<AddrModeNone, 0x33, (outs GPR:$rz), (ins operand:$offset),
+class I_18_Z_L<bits<3> sop, string op, dag outs, dag ins, list<dag> pattern>
+    : CSKY32Inst<AddrModeNone, 0x33, outs, ins,
                  !strconcat(op, "\t$rz, $offset"), pattern> {
   bits<5> rz;
   bits<18> offset;
@@ -100,10 +100,9 @@ class I_16_MOV<bits<5> sop, string op, ImmLeaf ImmType>
 
 // Format< OP[6] | SOP[5] | RZ[5] | OFFSET[16] >
 // Instructions(1): lrw32
-class I_16_Z_L<bits<5> sop, string op, Operand operand, list<dag> pattern>
-    : CSKY32Inst<AddrModeNone, 0x3a,
-                 (outs GPR:$rz), (ins operand:$imm16),
-                 !strconcat(op, "\t$rz, [$imm16]"), pattern> {
+class I_16_Z_L<bits<5> sop, string op, dag ins, list<dag> pattern>
+  : CSKY32Inst<AddrModeNone, 0x3a, (outs GPR:$rz), ins,
+  !strconcat(op, "\t$rz, [$imm16]"), pattern> {
   bits<5> rz;
   bits<16> imm16;
   let Inst{25 - 21} = sop;
@@ -122,13 +121,6 @@ class I_16_L<bits<5> sop, dag outs, dag ins, string op, list<dag> pattern>
   let Inst{15 - 0} = imm16;
 }
 
-// bt32, bf32, br32, jmpi32
-class I_16_L_B<bits<5> sop, string op, Operand operand, list<dag> pattern>
-    : I_16_L<sop, (outs), (ins operand:$imm16, CARRY:$ca), op, pattern> {
-  let isBranch = 1;
-  let isTerminator = 1;
-}
-
 // Format< OP[6] | SOP[5] | RX[5] | 0000000000000000[16] >
 // Instructions(2): jmp32, jsr32
 class I_16_JX<bits<5> sop, string op, list<dag> pattern>
@@ -169,9 +161,9 @@ class I_16_RET<bits<5> sop, bits<5> pcode, string op, list<dag> pattern>
 
 // Format< OP[6] | SOP[5] | RX[5] | IMM16[16] >
 // Instructions(3): cmpnei32, cmphsi32, cmplti32
-class I_16_X<bits<5> sop, string op>
+class I_16_X<bits<5> sop, string op, Operand operand>
     : CSKY32Inst<AddrModeNone, 0x3a, (outs CARRY:$ca),
-    (ins GPR:$rx, i32imm:$imm16), !strconcat(op, "\t$rx, $imm16"), []> {
+    (ins GPR:$rx, operand:$imm16), !strconcat(op, "\t$rx, $imm16"), []> {
   bits<16> imm16;
   bits<5> rx;
   let Inst{25 - 21} = sop;
@@ -211,7 +203,7 @@ class I_12<bits<4> sop, string op, SDNode node, ImmLeaf ImmType>
 
 class I_LDST<AddrMode am, bits<6> opcode, bits<4> sop, dag outs, dag ins,
              string op, list<dag> pattern>
-    : CSKY32Inst<am, opcode, outs, ins, !strconcat(op, "\t$rz, ($rx, $imm12)"),
+    : CSKY32Inst<am, opcode, outs, ins, !strconcat(op, "\t$rz, ($rx, ${imm12})"),
                  pattern> {
   bits<5> rx;
   bits<5> rz;
@@ -298,13 +290,13 @@ class I_5_YX<bits<6> opcode, dag outs, dag ins, string op, list<dag> pattern,
 
 // Format< OP[6] | LSB[5] | RX[5] | SOP[6] | MSB[5] | RZ[5]>
 // Instructions(6): zext32, zextb32, zexth32, sext32, sextb32, sexth32
-class I_5_XZ_U<bits<6> sop, bits<5> lsb, bits<5> msb, dag outs, dag ins,
-               string op, list<dag> pattern>
-    : CSKY32Inst<AddrModeNone, 0x31, outs, ins,
-                 op #"\t$rz, $rx, " #!cast<int>(msb) #", " #!cast<int>(lsb),
+class I_5_XZ_U<bits<6> sop, dag outs, dag ins, string op, list<dag> pattern>
+    : CSKY32Inst<AddrModeNone, 0x31, outs, ins, op #"\t$rz, $rx, $msb, $lsb",
                  pattern> {
   bits<5> rx;
   bits<5> rz;
+  bits<5> msb;
+  bits<5> lsb;
   let Inst{25 - 21} = lsb; // lsb
   let Inst{20 - 16} = rx;
   let Inst{15 - 10} = sop;
@@ -313,12 +305,12 @@ class I_5_XZ_U<bits<6> sop, bits<5> lsb, bits<5> msb, dag outs, dag ins,
 }
 
 // sextb, sexth
-class I_5_XZ_US<bits<6> sop, bits<5> lsb, bits<5> msb, string op, SDNode opnode,
-  ValueType type> : I_5_XZ_U<sop, lsb, msb,
-  (outs GPR:$rz), (ins GPR:$rx),op, [(set GPR:$rz, (opnode GPR:$rx, type))]>;
+class I_5_XZ_US<bits<6> sop, string op, SDNode opnode,
+  ValueType type> : I_5_XZ_U<sop, (outs GPR:$rz), (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), op,
+    [(set GPR:$rz, (opnode GPR:$rx, type))]>;
 
-class I_5_XZ_UZ<bits<6> sop, bits<5> lsb, bits<5> msb, string op, int v>
-    : I_5_XZ_U<sop, lsb, msb, (outs GPR:$rz), (ins GPR:$rx), op,
+class I_5_XZ_UZ<bits<6> sop, string op, int v>
+    : I_5_XZ_U<sop, (outs GPR:$rz), (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), op,
     [(set GPR:$rz, (and GPR:$rx, (i32 v)))]>;
 
 // Format< OP[6] | RZ[5] | RX[5] | SOP[6] | SIZE[5] | LSB[5]>
@@ -401,27 +393,26 @@ class R_YXZ_SP_F1<bits<6> sop, bits<5> pcode, PatFrag opnode, string op,
 // Format< OP[6] | RY[5] | RX[5] | SOP[6] | PCODE[5] | RZ[5] >
 // Instructions:(8) ldr32.b, ldr32.h, ldr32.bs, ldr32.hs, ldr32.w,
 //                  str32.b, str32.h, str32.w
-class R_YXZ_LDST<bits<6> opcode, bits<6> sop, bits<5> pcode, int no, dag outs,
+class R_YXZ_LDST<bits<6> opcode, bits<6> sop, dag outs,
                  dag ins, string op, list<dag> pattern>
     : CSKY32Inst<AddrModeNone, opcode, outs, ins,
-                 op #"\t$rz, ($rx, $ry << " #no #")", pattern> {
+                 op # "\t$rz, ($rx, $ry << ${imm})", pattern> {
   bits<5> rx;
   bits<5> ry;
   bits<5> rz;
+  bits<5> imm;
   let Inst{25 - 21} = ry; // ry;
   let Inst{20 - 16} = rx; // rx;
   let Inst{15 - 10} = sop;
-  let Inst{9 - 5} = pcode; // pcode;
+  let Inst{9 - 5} = imm;  // pcode;
   let Inst{4 - 0} = rz;
 }
 
-class I_LDR<bits<6> sop, bits<5> pcode, string op, int no>
-    : R_YXZ_LDST<0x34, sop, pcode, no,
-    (outs GPR:$rz), (ins GPR:$rx, GPR:$ry), op, []>;
+class I_LDR<bits<6> sop, string op> : R_YXZ_LDST<0x34, sop,
+  (outs GPR:$rz), (ins GPR:$rx, GPR:$ry, uimm_shift:$imm), op, []>;
 
-class I_STR<bits<6> sop, bits<5> pcode, string op, int no>
-    : R_YXZ_LDST<0x35, sop, pcode, no, (outs),
-    (ins GPR:$rz, GPR:$rx, GPR:$ry), op, []>;
+class I_STR<bits<6> sop, string op> : R_YXZ_LDST<0x35, sop,
+  (outs), (ins GPR:$rz, GPR:$rx, GPR:$ry, uimm_shift:$imm), op, []>;
 
 // Format< OP[6] | RX[5] | RX[5] | SOP[6] | PCODE[5] | RZ[5] >
 // Instructions:(1) not32
index 88985a9..a3e5c9c 100644 (file)
@@ -10,7 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-include "CSKYInstrFormats.td"
 
 //===----------------------------------------------------------------------===//
 // CSKY specific DAG Nodes.
@@ -48,7 +47,10 @@ class oimm<int num> : Operand<i32>,
 class uimm<int num, int shift = 0> : Operand<i32>,
   ImmLeaf<i32, "return isShiftedUInt<"#num#", "#shift#">(Imm);"> {
   let EncoderMethod = "getImmOpValue<"#shift#">";
-  let ParserMatchClass = UImmAsmOperand<num>;
+  let ParserMatchClass =
+    !if(!ne(shift, 0),
+        UImmAsmOperand<num, "Shift"#shift>,
+        UImmAsmOperand<num>);
 }
 
 class simm<int num, int shift = 0> : Operand<i32>,
@@ -65,13 +67,38 @@ class nimm<int num> : Operand<i32>,
   let ParserMatchClass = UImmAsmOperand<num>;
 }
 
+def uimm32_hi16 : SDNodeXForm<imm, [{
+  return CurDAG->getTargetConstant((N->getZExtValue() >> 16) & 0xFFFF,
+    SDLoc(N), MVT::i32);
+}]>;
+def uimm16_16_xform : Operand<i32>,
+  ImmLeaf<i32, "return isShiftedUInt<16, 16>(Imm);", uimm32_hi16> {
+  let ParserMatchClass = UImmAsmOperand<16>;
+}
+
+def uimm_shift : Operand<i32>, ImmLeaf<i32, "return isUInt<2>(Imm);"> {
+  let EncoderMethod = "getImmShiftOpValue";
+  let ParserMatchClass = UImmAsmOperand<2>;
+}
+
 
 def oimm12 : oimm<12>;
+def oimm16 : oimm<16>;
 
 def nimm12 : nimm<12>;
 
 def uimm5 : uimm<5>;
 def uimm12 : uimm<12>;
+def uimm12_1 : uimm<12, 1>;
+def uimm12_2 : uimm<12, 2>;
+def uimm16 : uimm<16>;
+
+
+//===----------------------------------------------------------------------===//
+// Instruction Formats
+//===----------------------------------------------------------------------===//
+
+include "CSKYInstrFormats.td"
 
 //===----------------------------------------------------------------------===//
 // Instruction definitions.
@@ -81,10 +108,18 @@ class TriOpFrag<dag res> : PatFrag<(ops node: $LHS, node:$MHS, node:$RHS), res>;
 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
 class UnOpFrag<dag res> : PatFrag<(ops node:$Src), res>;
 
+
+
+//===----------------------------------------------------------------------===//
+// Basic ALU instructions.
+//===----------------------------------------------------------------------===//
+
 def ADDI32 : I_12<0x0, "addi32", add, oimm12>;
 def SUBI32 : I_12<0x1, "subi32", sub, oimm12>;
 def ANDI32 : I_12<0x2, "andi32", and, uimm12>;
 def ANDNI32 : I_12<0x3, "andni32", and, nimm12>;
+def ORI32 : I_16_ZX<"ori32", uimm16,
+  [(set GPR:$rz, (or GPR:$rx, uimm16:$imm16))]>;
 def XORI32 : I_12<0x4, "xori32", xor, uimm12>;
 def LSLI32 : I_5_XZ<0x12, 0x1, "lsli32",
   (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5),
@@ -95,8 +130,9 @@ def LSRI32 : I_5_XZ<0x12, 0x2, "lsri32",
 def ASRI32 : I_5_XZ<0x12, 0x4, "asri32",
   (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5),
   [(set GPR:$rz, (sra GPR:$rx, uimm5:$imm5))]>;
-
-
+def ROTLI32 : I_5_XZ<0x12, 0x8, "rotli32",
+  (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5),
+  [(set GPR:$rz, (rotl GPR:$rx, uimm5:$imm5))]>;
 
 def ADDU32 : R_YXZ_SP_F1<0x0, 0x1,
   BinOpFrag<(add node:$LHS, node:$RHS)>, "addu32", 1>;
@@ -124,6 +160,72 @@ def DIVS32 : R_YXZ_SP_F1<0x20, 0x2,
   BinOpFrag<(sdiv node:$LHS, node:$RHS)>, "divs32">;
 def DIVU32 : R_YXZ_SP_F1<0x20, 0x1,
   BinOpFrag<(udiv node:$LHS, node:$RHS)>, "divu32">;
+def IXH32 : R_YXZ_SP_F1<0x2, 0x1,
+  BinOpFrag<(add node:$LHS, (shl node:$RHS, (i32 1)))>, "ixh32">;
+def IXW32 : R_YXZ_SP_F1<0x2, 0x2,
+  BinOpFrag<(add node:$LHS, (shl node:$RHS, (i32 2)))>, "ixw32">;
+def IXD32 : R_YXZ_SP_F1<0x2, 0x4,
+  BinOpFrag<(add node:$LHS, (shl node:$RHS, (i32 3)))>, "ixd32">;
 
 def NOT32 : R_XXZ<0b001001, 0b00100, (outs GPR:$rz), (ins GPR:$rx),
   "not32", [(set GPR:$rz, (not GPR:$rx))]>;
+
+def SEXT : I_5_XZ_U<0x16, (outs GPR:$rz), (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "sext32",
+    []>;
+def ZEXT : I_5_XZ_U<0x15, (outs GPR:$rz), (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "zext32",
+    []>;
+
+
+let isCommutable = 1 in
+  def ADDC32 : R_YXZ<0x31, 0x0, 0x2, (outs GPR:$rz, CARRY:$cout),
+    (ins GPR:$rx, GPR:$ry, CARRY:$cin), "addc32", []>;
+def SUBC32 : R_YXZ<0x31, 0x0, 0x8, (outs GPR:$rz, CARRY:$cout),
+  (ins GPR:$rx, GPR:$ry, CARRY:$cin), "subc32", []>;
+
+//===----------------------------------------------------------------------===//
+// Load & Store instructions.
+//===----------------------------------------------------------------------===//
+
+def LD32B : I_LD<AddrMode32B, 0x0, "ld32.b", uimm12>;
+def LD32H : I_LD<AddrMode32H, 0x1, "ld32.h", uimm12_1>;
+def LD32W : I_LD<AddrMode32WD, 0x2, "ld32.w", uimm12_2>;
+def LD32BS : I_LD<AddrMode32B, 0x4, "ld32.bs", uimm12>;
+def LD32HS : I_LD<AddrMode32H, 0x5, "ld32.hs", uimm12_1>;
+
+def LDR32B :  I_LDR<0x0, "ldr32.b">;
+def LDR32BS :  I_LDR<0x4, "ldr32.bs">;
+def LDR32H :  I_LDR<0x1, "ldr32.h">;
+def LDR32HS :  I_LDR<0x5, "ldr32.hs">;
+def LDR32W :  I_LDR<0x2, "ldr32.w">;
+
+def ST32B : I_ST<AddrMode32B, 0x0, "st32.b", uimm12>;
+def ST32H : I_ST<AddrMode32H, 0x1, "st32.h", uimm12_1>;
+def ST32W : I_ST<AddrMode32WD, 0x2, "st32.w", uimm12_2>;
+
+def STR32B :  I_STR<0x0, "str32.b">;
+def STR32H :  I_STR<0x1, "str32.h">;
+def STR32W :  I_STR<0x2, "str32.w">;
+
+//===----------------------------------------------------------------------===//
+// Compare instructions.
+//===----------------------------------------------------------------------===//
+
+def CMPNEI32 : I_16_X<0x1A, "cmpnei32", uimm16>;
+def CMPHSI32 : I_16_X<0x18, "cmphsi32", oimm16>;
+def CMPLTI32 : I_16_X<0x19, "cmplti32", oimm16>;
+def CMPNE32 : R_YX<0x1, 0x4, "cmpne32">;
+def CMPHS32 : R_YX<0x1, 0x1, "cmphs32">;
+def CMPLT32 : R_YX<0x1, 0x2, "cmplt32">;
+
+//===----------------------------------------------------------------------===//
+// Data move instructions.
+//===----------------------------------------------------------------------===//
+
+def MOVT32 : R_ZX<0x3, 0x2, "movt32", []>;
+def MOVF32 : R_ZX<0x3, 0x1, "movf32", []>;
+def MOV32 : R_XZ<0x12, 0x1, "mov32">;
+def MOVI32 : I_16_MOV<0x10, "movi32", uimm16>;
+def MOVIH32 : I_16_MOV<0x11, "movih32", uimm16_16_xform>;
+
+def MVC32 : R_Z_1<0x1, 0x8, "mvc32">;
+def MVCV32 : R_Z_1<0x1, 0x10, "mvcv32">;
index c850a4b..99a6763 100644 (file)
@@ -54,6 +54,14 @@ public:
   unsigned getOImmOpValue(const MCInst &MI, unsigned Idx,
                           SmallVectorImpl<MCFixup> &Fixups,
                           const MCSubtargetInfo &STI) const;
+
+  unsigned getImmShiftOpValue(const MCInst &MI, unsigned Idx,
+                              SmallVectorImpl<MCFixup> &Fixups,
+                              const MCSubtargetInfo &STI) const {
+    const MCOperand &MO = MI.getOperand(Idx);
+    assert(MO.isImm() && "Unexpected MO type.");
+    return 1 << MO.getImm();
+  }
 };
 
 } // namespace llvm
index 17f6605..71920e7 100644 (file)
@@ -32,6 +32,33 @@ lsri32 a0, sp, 2
 # CHECK-ASM: encoding: [0x4e,0xc4,0x80,0x48]
 asri32 a0, sp, 2
 
+# CHECK-ASM: ori32 a0, sp, 2
+# CHECK-ASM: encoding: [0x0e,0xec,0x02,0x00]
+ori32 a0, sp, 2
+
+# CHECK-ASM: rotli32 a0, sp, 2
+# CHECK-ASM: encoding: [0x4e,0xc4,0x00,0x49]
+rotli32 a0, sp, 2
+
+# CHECK-ASM: cmpnei32 a0, 2
+# CHECK-ASM: encoding: [0x40,0xeb,0x02,0x00]
+cmpnei32 a0, 2
+
+# CHECK-ASM: cmphsi32 a0, 2
+# CHECK-ASM: encoding: [0x00,0xeb,0x01,0x00]
+cmphsi32 a0, 2
+
+# CHECK-ASM: cmplti32 a0, 2
+# CHECK-ASM: encoding: [0x20,0xeb,0x01,0x00]
+cmplti32 a0, 2
+
+# CHECK-ASM: movi32 a0, 2
+# CHECK-ASM: encoding: [0x00,0xea,0x02,0x00]
+movi32 a0, 2
+
+# CHECK-ASM: movih32 a0, 2
+# CHECK-ASM: encoding: [0x20,0xea,0x02,0x00]
+movih32 a0, 2
 
 # CHECK-ASM: addu32 a3, l0, l1
 # CHECK-ASM: encoding: [0xa4,0xc4,0x23,0x00]
@@ -85,10 +112,133 @@ divs32 a3, l0, l1
 # CHECK-ASM: encoding: [0xa4,0xc4,0x23,0x80]
 divu32 a3, l0, l1
 
+# CHECK-ASM: ixh32 a3, l0, l1
+# CHECK-ASM: encoding: [0xa4,0xc4,0x23,0x08]
+ixh32 a3, l0, l1
+
+# CHECK-ASM: ixw32 a3, l0, l1
+# CHECK-ASM: encoding: [0xa4,0xc4,0x43,0x08]
+ixw32 a3, l0, l1
+
+# CHECK-ASM: ixd32 a3, l0, l1
+# CHECK-ASM: encoding: [0xa4,0xc4,0x83,0x08]
+ixd32 a3, l0, l1
+
+# CHECK-ASM: addc32 a3, l0, l1
+# CHECK-ASM: encoding: [0xa4,0xc4,0x43,0x00]
+addc32 a3, l0, l1
+
+# CHECK-ASM: subc32 a3, l0, l1
+# CHECK-ASM: encoding: [0xa4,0xc4,0x03,0x01]
+subc32 a3, l0, l1
+
+# CHECK-ASM: ld32.b a0, (sp, 2)
+# CHECK-ASM: encoding: [0x0e,0xd8,0x02,0x00]
+ld32.b a0, (sp, 2)
+
+# CHECK-ASM: ld32.bs a0, (sp, 2)
+# CHECK-ASM: encoding: [0x0e,0xd8,0x02,0x40]
+ld32.bs a0, (sp, 2)
+
+# CHECK-ASM: ld32.h a0, (sp, 2)
+# CHECK-ASM: encoding: [0x0e,0xd8,0x01,0x10]
+ld32.h a0, (sp, 2)
+
+# CHECK-ASM: ld32.hs a0, (sp, 2)
+# CHECK-ASM: encoding: [0x0e,0xd8,0x01,0x50]
+ld32.hs a0, (sp, 2)
+
+# CHECK-ASM: ld32.w a0, (sp, 4)
+# CHECK-ASM: encoding: [0x0e,0xd8,0x01,0x20]
+ld32.w a0, (sp, 4)
+
+# CHECK-ASM: ldr32.b a0, (sp, l1 << 2)
+# CHECK-ASM: encoding: [0xae,0xd0,0x80,0x00]
+ldr32.b a0, (sp, l1 << 2)
+
+# CHECK-ASM: ldr32.bs a0, (sp, l1 << 2)
+# CHECK-ASM: encoding: [0xae,0xd0,0x80,0x10]
+ldr32.bs a0, (sp, l1 << 2)
+
+# CHECK-ASM: ldr32.h a0, (sp, l1 << 3)
+# CHECK-ASM: encoding: [0xae,0xd0,0x00,0x05]
+ldr32.h a0, (sp, l1 << 3)
+
+# CHECK-ASM: ldr32.hs a0, (sp, l1 << 3)
+# CHECK-ASM: encoding: [0xae,0xd0,0x00,0x15]
+ldr32.hs a0, (sp, l1 << 3)
+
+# CHECK-ASM: ldr32.w a0, (sp, l1 << 3)
+# CHECK-ASM: encoding: [0xae,0xd0,0x00,0x09]
+ldr32.w a0, (sp, l1 << 3)
+
+# CHECK-ASM: st32.b a0, (sp, 2)
+# CHECK-ASM: encoding: [0x0e,0xdc,0x02,0x00]
+st32.b a0, (sp, 2)
+
+# CHECK-ASM: st32.h a0, (sp, 2)
+# CHECK-ASM: encoding: [0x0e,0xdc,0x01,0x10]
+st32.h a0, (sp, 2)
+
+# CHECK-ASM: st32.w a0, (sp, 4)
+# CHECK-ASM: encoding: [0x0e,0xdc,0x01,0x20]
+st32.w a0, (sp, 4)
+
+# CHECK-ASM: str32.b a0, (sp, l1 << 2)
+# CHECK-ASM: encoding: [0xae,0xd4,0x80,0x00]
+str32.b a0, (sp, l1 << 2)
+
+# CHECK-ASM: str32.h a0, (sp, l1 << 3)
+# CHECK-ASM: encoding: [0xae,0xd4,0x00,0x05]
+str32.h a0, (sp, l1 << 3)
+
+# CHECK-ASM: str32.w a0, (sp, l1 << 3)
+# CHECK-ASM: encoding: [0xae,0xd4,0x00,0x09]
+str32.w a0, (sp, l1 << 3)
+
 # CHECK-ASM: not32 a3, l0
 # CHECK-ASM: encoding: [0x84,0xc4,0x83,0x24]
 not32 a3, l0
 
+# CHECK-ASM: mov32 a3, l0
+# CHECK-ASM: encoding: [0x04,0xc4,0x23,0x48]
+mov32 a3, l0
+
+# CHECK-ASM: movt32 a3, l0
+# CHECK-ASM: encoding: [0x64,0xc4,0x40,0x0c]
+movt32 a3, l0
+
+# CHECK-ASM: movf32 a3, l0
+# CHECK-ASM: encoding: [0x64,0xc4,0x20,0x0c]
+movf32 a3, l0
+
+# CHECK-ASM: mvc32 a3
+# CHECK-ASM: encoding: [0x00,0xc4,0x03,0x05]
+mvc32 a3
+
+# CHECK-ASM: mvcv32 a3
+# CHECK-ASM: encoding: [0x00,0xc4,0x03,0x06]
+mvcv32 a3
+
+# CHECK-ASM: cmpne32 a3, l0
+# CHECK-ASM: encoding: [0x83,0xc4,0x80,0x04]
+cmpne32 a3, l0
+
+# CHECK-ASM: cmphs32 a3, l0
+# CHECK-ASM: encoding: [0x83,0xc4,0x20,0x04]
+cmphs32 a3, l0
+
+# CHECK-ASM: cmplt32 a3, l0
+# CHECK-ASM: encoding: [0x83,0xc4,0x40,0x04]
+cmplt32 a3, l0
+
+# CHECK-ASM: zext32 a3, l0, 7, 0
+# CHECK-ASM: encoding: [0x04,0xc4,0xe3,0x54]
+zext32 a3, l0, 7, 0
+
+# CHECK-ASM: sext32 a3, l0, 7, 0
+# CHECK-ASM: encoding: [0x04,0xc4,0xe3,0x58]
+sext32 a3, l0, 7, 0
 
 # RUN: not llvm-mc -triple csky --defsym=ERR=1 < %s 2>&1 | FileCheck %s
 
@@ -106,7 +256,37 @@ xori32 a0, a0, 4096 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer
 lsli32 a0, a0, 32 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [0, 31]
 lsri32 a0, a0, 32 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [0, 31]
 asri32 a0, a0, 32 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [0, 31]
-
+rotli32 a0, a0, 32 # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 31]
+
+# uimm12(shift0)/uimm12_1/uimm12_2
+ld32.b a0, (a0, -1)  # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 4095]
+ld32.h a0, (a0, 4095)  # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 2 bytes in the range [0, 4094]
+ld32.h a0, (a0, 4093)  # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 2 bytes in the range [0, 4094]
+ld32.w a0, (a0, 4093)  # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 4 bytes in the range [0, 4092]
+ld32.w a0, (a0, 2)  # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 4 bytes in the range [0, 4092]
+ldr32.b a0, (a0, a1 << 4) # CHECK: :[[@LINE]]:24: error: immediate must be an integer in the range [0, 3]
+ldr32.bs a0, (a0, a1 << 4) # CHECK: :[[@LINE]]:25: error: immediate must be an integer in the range [0, 3]
+ldr32.h a0, (a0, a1 << -1) # CHECK: :[[@LINE]]:24: error: immediate must be an integer in the range [0, 3]
+ldr32.hs a0, (a0, a1 << 4) # CHECK: :[[@LINE]]:25: error: immediate must be an integer in the range [0, 3]
+ldr32.w a0, (a0, a1 << 4) # CHECK: :[[@LINE]]:24: error: immediate must be an integer in the range [0, 3]
+
+st32.b a0, (a0, -1)  # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 4095]
+st32.h a0, (a0, 4095)  # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 2 bytes in the range [0, 4094]
+st32.h a0, (a0, 4093)  # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 2 bytes in the range [0, 4094]
+st32.w a0, (a0, 4093)  # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 4 bytes in the range [0, 4092]
+st32.w a0, (a0, 2)  # CHECK: :[[@LINE]]:17: error: immediate must be a multiple of 4 bytes in the range [0, 4092]
+
+str32.b a0, (a0, a1 << 4) # CHECK: :[[@LINE]]:24: error: immediate must be an integer in the range [0, 3]
+str32.h a0, (a0, a1 << -1) # CHECK: :[[@LINE]]:24: error: immediate must be an integer in the range [0, 3]
+str32.w a0, (a0, a1 << 4) # CHECK: :[[@LINE]]:24: error: immediate must be an integer in the range [0, 3]
+
+# uimm16/oimm16
+ori32 a0, a0, 0x10000 # CHECK: :[[@LINE]]:15: error: immediate must be an integer in the range [0, 65535]
+cmpnei32 a0, 0x10000 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 65535]
+cmphsi32 a0, 0x10001 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [1, 65536]
+cmplti32 a0, 0 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [1, 65536]
+movi32 a0, 0x10000 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 65535]
+movih32 a0, 0x10000 # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [0, 65535]
 
 # Invalid mnemonics
 subs t0, t2, t1 # CHECK: :[[#@LINE]]:1: error: unrecognized instruction mnemonic
@@ -122,7 +302,7 @@ xori32 sp, 22, 220 # CHECK: :[[#@LINE]]:12: error: invalid operand for instructi
 subu32 t0, t2, 1 # CHECK: :[[#@LINE]]:16: error: invalid operand for instruction
 
 # Too many operands
-subu32 t2, t3, 0x50, 0x60 # CHECK: :[[#@LINE]]:22: error: invalid operand for instruction
+subi32 t2, t3, 0x50, 0x60 # CHECK: :[[@LINE]]:22: error: invalid operand for instruction
 
 # Too few operands
 xori32 a0, a1 # CHECK: :[[#@LINE]]:1: error: too few operands for instruction