[CSKY] Add CSKY 16-bit instruction format and encoding
authorZi Xuan Wu <zixuan.wu@linux.alibaba.com>
Mon, 8 Nov 2021 02:02:15 +0000 (10:02 +0800)
committerZi Xuan Wu <zixuan.wu@linux.alibaba.com>
Mon, 8 Nov 2021 02:02:15 +0000 (10:02 +0800)
CSKY is a ARCH which supports mixture of 16-bit and 32-bit instructions natively,
and there is not an indivual predictor or feature to enable/disable 16-bit instruction.
So I think it's better to add 16-bit instruction early, and naturally to use 16-bit and 32-bit instructions.

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

llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
llvm/lib/Target/CSKY/CSKY.td
llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td [new file with mode: 0644]
llvm/lib/Target/CSKY/CSKYInstrInfo.td
llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td [new file with mode: 0644]
llvm/lib/Target/CSKY/CSKYRegisterInfo.td
llvm/lib/Target/CSKY/CSKYSubtarget.cpp
llvm/lib/Target/CSKY/CSKYSubtarget.h
llvm/lib/Target/CSKY/CSKYTargetMachine.h
llvm/test/MC/CSKY/basic-16bit.s [new file with mode: 0644]

index df85c8c..ebc04b4 100644 (file)
@@ -755,6 +755,10 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
     return Error(ErrorLoc, "register is out of range");
   }
+  case Match_InvalidSPOperand: {
+    SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
+    return Error(ErrorLoc, "operand must be sp register");
+  }
   case Match_RequiresSameSrcAndDst: {
     SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
     return Error(ErrorLoc, "src and dst operand must be same");
index 499ff4f..e26781c 100644 (file)
@@ -12,6 +12,12 @@ include "llvm/Target/Target.td"
 // CSKY subtarget features and instruction predicates.
 //===----------------------------------------------------------------------===//
 
+def FeatureBTST16 : SubtargetFeature<"btst16", "HasBTST16", "true",
+                                     "Use the 16-bit btsti instruction">;
+def HasBTST16 : Predicate<"Subtarget->hasBTST16()">,
+                   AssemblerPredicate<(all_of FeatureBTST16),
+                   "Use the 16-bit btsti instruction">;
+
 // Atomic Support
 def FeatureExtendLrw : SubtargetFeature<"elrw", "HasExtendLrw", "true",
                                         "Use the extend LRW instruction">;
@@ -19,6 +25,12 @@ def HasExtendLrw : Predicate<"Subtarget->hasExtendLrw()">,
                    AssemblerPredicate<(all_of FeatureExtendLrw),
                    "Use the extend LRW instruction">;
 
+def FeatureJAVA
+    : SubtargetFeature<"java", "HasJAVA", "true", "Enable java instructions">;
+def HasJAVA : Predicate<"Subtarget->hasJAVA()">,
+              AssemblerPredicate<(all_of FeatureJAVA),
+              "Enable java instructions">;
+
 def FeatureDoloop : SubtargetFeature<"doloop", "HasDoloop", "true",
                                      "Enable doloop instructions">;
 def HasDoloop : Predicate<"Subtarget->hasDoloop()">,
diff --git a/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td b/llvm/lib/Target/CSKY/CSKYInstrFormats16Instr.td
new file mode 100644 (file)
index 0000000..6d42bdd
--- /dev/null
@@ -0,0 +1,219 @@
+//===- CSKYInstrFormats16Instr.td - 16-bit Instr. Formats -*- tablegen --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+class J16<bits<5> sop, string opstr, dag ins>
+  : CSKY16Inst<AddrModeNone, (outs), ins,
+    !strconcat(opstr, "\t$offset"), []> {
+  bits<10> offset;
+  let Inst{15} = 0;
+  let Inst{14 - 10} = sop;
+  let Inst{9 - 0} = offset;
+}
+
+class J16_B<bits<5> sop, string opstr>
+  : CSKY16Inst<AddrModeNone, (outs), (ins CARRY:$ca, br_symbol_16bit:$offset),
+    !strconcat(opstr, "\t$offset"), []> {
+  bits<10> offset;
+  let Inst{15} = 0;
+  let Inst{14 - 10} = sop;
+  let Inst{9 - 0} = offset;
+}
+
+class R16_XYZ<bits<2> sop, string opstr, SDNode opnode> : CSKY16Inst<AddrModeNone,
+  (outs mGPR:$rz), (ins mGPR:$rx, mGPR:$ry), !strconcat(opstr, "\t$rz, $rx, $ry"),
+  [(set mGPR:$rz, (opnode mGPR:$rx, mGPR:$ry)) ]> {
+  bits<3> rz;
+  bits<3> rx;
+  bits<3> ry;
+  let Inst{15 - 11} = 0b01011;
+  let Inst{10 - 8} = rx;
+  let Inst{7 - 5} = rz;
+  let Inst{4 - 2} = ry;
+  let Inst{1, 0} = sop;
+}
+
+class R16_XZ_BINOP<bits<4> op, bits<2> sop, string opstr, PatFrag opnode> : CSKY16Inst<
+  AddrModeNone, (outs sGPR:$rz), (ins sGPR:$rZ, sGPR:$rx), !strconcat(opstr, "\t$rz, $rx"),
+  [(set sGPR:$rz, (opnode sGPR:$rZ, sGPR:$rx))]> {
+  bits<4> rz;
+  bits<4> rx;
+  let Inst{15, 14} = 0b01;
+  let Inst{13 - 10} = op;
+  let Inst{9 - 6} = rz;
+  let Inst{5 - 2} = rx;
+  let Inst{1, 0} = sop;
+  let Constraints = "$rz = $rZ";
+}
+
+class R16_XZ_BINOP_NOPat<bits<4> op, bits<2> sop, string opstr> : CSKY16Inst<
+  AddrModeNone, (outs sGPR:$rz), (ins sGPR:$rZ, sGPR:$rx), !strconcat(opstr, "\t$rz, $rx"),
+  []> {
+  bits<4> rz;
+  bits<4> rx;
+  let Inst{15, 14} = 0b01;
+  let Inst{13 - 10} = op;
+  let Inst{9 - 6} = rz;
+  let Inst{5 - 2} = rx;
+  let Inst{1, 0} = sop;
+  let Constraints = "$rz = $rZ";
+}
+
+class R16_XZ_BINOP_C<bits<4> op, bits<2> sop, string opstr> : CSKY16Inst<
+  AddrModeNone, (outs sGPR:$rz, CARRY:$cout),
+  (ins sGPR:$rZ, sGPR:$rx, CARRY:$cin), !strconcat(opstr, "\t$rz, $rx"), []> {
+  bits<4> rz;
+  bits<4> rx;
+  let Inst{15, 14} = 0b01;
+  let Inst{13 - 10} = op;
+  let Inst{9 - 6} = rz;
+  let Inst{5 - 2} = rx;
+  let Inst{1, 0} = sop;
+  let Constraints = "$rz = $rZ";
+}
+
+class R16_XZ_UNOP<bits<4> op, bits<2> sop, string opstr> : CSKY16Inst<
+  AddrModeNone, (outs sGPR:$rz), (ins sGPR:$rx), !strconcat(opstr, "\t$rz, $rx"),
+  []> {
+  bits<4> rz;
+  bits<4> rx;
+  let Inst{15, 14} = 0b01;
+  let Inst{13 - 10} = op;
+  let Inst{9 - 6} = rz;
+  let Inst{5 - 2} = rx;
+  let Inst{1, 0} = sop;
+}
+
+class R16_XY_CMP<bits<2> sop, string opstr> : CSKY16Inst<
+  AddrModeNone, (outs CARRY:$ca), (ins sGPR:$rx, sGPR:$ry), !strconcat(opstr, "\t$rx, $ry"),
+  []> {
+  bits<4> ry;
+  bits<4> rx;
+  let Inst{15, 14} = 0b01;
+  let Inst{13 - 10} = 0b1001;
+  let Inst{9 - 6} = ry;
+  let Inst{5 - 2} = rx;
+  let Inst{1, 0} = sop;
+  let isCompare = 1;
+}
+
+class R16_X_J<bits<8> op_rz, bits<2> sop, string opstr> : CSKY16Inst<
+  AddrModeNone, (outs), (ins sGPR:$rx), !strconcat(opstr, "\t$rx"), []> {
+  bits<4> rx;
+  let Inst{15, 14} = 0b01;
+  let Inst{13 - 6} = op_rz;
+  let Inst{5 - 2} = rx;
+  let Inst{1, 0} = sop;
+}
+
+class I16_Z_8<bits<3> op, dag ins, string asmstr>
+  : CSKY16Inst<AddrModeNone, (outs mGPR:$rz), ins, asmstr, []> {
+  bits<3> rz;
+  bits<8> imm8;
+  let Inst{15, 14} = 0b00;
+  let Inst{13 - 11} = op;
+  let Inst{10 - 8} = rz;
+  let Inst{7 - 0} = imm8;
+}
+
+class I16_Z_5<bits<3> sop, dag outs, dag ins,string opstr>
+  : CSKY16Inst<AddrModeNone, outs, ins,
+  !strconcat(opstr, "\t$rz, $imm5"), []> {
+  bits<3> rz;
+  bits<5> imm5;
+  let Inst{15, 14} = 0b00;
+  let Inst{13 - 11} = 0b111;
+  let Inst{10 - 8} = rz;
+  let Inst{7 - 5} = sop;
+  let Inst{4 - 0} = imm5;
+}
+
+class I16_X_CMP<bits<3> sop, string opstr, Operand Immoperand> : CSKY16Inst<
+  AddrModeNone, (outs CARRY:$ca), (ins mGPR:$rx, Immoperand:$imm5),
+  !strconcat(opstr, "\t$rx, $imm5"), []> {
+  bits<3> rx;
+  bits<5> imm5;
+  let Inst{15, 14} = 0b00;
+  let Inst{13 - 11} = 0b111;
+  let Inst{10 - 8} = rx;
+  let Inst{7 - 5} = sop;
+  let Inst{4 - 0} = imm5;
+  let isCompare = 1;
+}
+
+class I16_SP_IMM7<bits<3> sop, string opstr> : CSKY16Inst<
+  AddrModeNone, (outs SPOp:$sp2), (ins SPOp:$sp1, uimm7_2:$imm7),
+  !strconcat(opstr, "\t$sp2, $sp1, $imm7"), []> {
+  bits<7> imm7;
+  let Inst{15, 14} = 0b00;
+  let Inst{13 - 10} = 0b0101;
+  let Inst{9, 8} = imm7{6,5};
+  let Inst{7 - 5} = sop;
+  let Inst{4 - 0} = imm7{4 - 0};
+}
+
+class I16_XZ_IMM5<bits<3> sop, string opstr, SDNode opnode> : CSKY16Inst<
+  AddrModeNone, (outs mGPR:$rz), (ins mGPR:$rx, uimm5:$imm5),
+  !strconcat(opstr, "\t$rz, $rx, $imm5"), [(set mGPR:$rz, (opnode mGPR:$rx, uimm5:$imm5))]> {
+  bits<3> rx;
+  bits<3> rz;
+  bits<5> imm5;
+  let Inst{15, 14} = 0b01;
+  let Inst{13 - 11} = sop;
+  let Inst{10 - 8} = rx;
+  let Inst{7 - 5} = rz;
+  let Inst{4 - 0} = imm5;
+}
+
+class I16_XZ_LDST<AddrMode am, bits<3> sop, string opstr, dag outs, dag ins>
+  : CSKY16Inst<am, outs, ins, !strconcat(opstr, "\t$rz, ($rx, ${imm})"),
+  []> {
+  bits<3> rx;
+  bits<3> rz;
+  bits<5> imm;
+  let Inst{15, 14} = 0b10;
+  let Inst{13 - 11} = sop;
+  let Inst{10 - 8} = rx;
+  let Inst{7 - 5} = rz;
+  let Inst{4 - 0} = imm;
+}
+
+class I16_ZSP_LDST<AddrMode am, bits<3> sop, string opstr, dag outs, dag ins> : CSKY16Inst<
+  am,  outs, ins, !strconcat(opstr, "\t$rz, ($sp, ${addr})"),
+  []> {
+  bits<3> rz;
+  bits<8> addr;
+  let Inst{15, 14} = 0b10;
+  let Inst{13 - 11} = sop;
+  let Inst{10 - 8} = addr{7 - 5};
+  let Inst{7 - 5} = rz;
+  let Inst{4 - 0} = addr{4 - 0};
+}
+
+class I16_XZ_IMM3<bits<2> sop, string opstr, SDNode opnode> : CSKY16Inst<
+  AddrModeNone, (outs mGPR:$rz), (ins mGPR:$rx, oimm3:$oimm3),
+  !strconcat(opstr, "\t$rz, $rx, $oimm3"), [(set mGPR:$rz, (opnode mGPR:$rx, oimm3:$oimm3))]> {
+  bits<3> rx;
+  bits<3> rz;
+  bits<3> oimm3;
+  let Inst{15, 14} = 0b01;
+  let Inst{13 - 11} = 0b011;
+  let Inst{10 - 8} = rx;
+  let Inst{7 - 5} = rz;
+  let Inst{4 - 2} = oimm3;
+  let Inst{1, 0} = sop;
+}
+
+class I16_BPushPop<bits<11> op, bits<2> uop, dag out, dag ins, string opstr> :
+  CSKY16Inst<AddrModeNone, out, ins, opstr, []>{
+  bits<3> rz;
+  let Inst{15- 5} = op;
+  let Inst{4 -2} = rz;
+  let Inst{1,0} = uop;
+  let Predicates = [HasJAVA];
+  let hasSideEffects = 1;
+}
index 628d5b5..9dda315 100644 (file)
@@ -947,3 +947,5 @@ def PseudoTLSLA32 : CSKYPseudo<(outs GPR:$dst1, GPR:$dst2),
 let hasSideEffects = 0, isNotDuplicable = 1 in
 def CONSTPOOL_ENTRY : CSKYPseudo<(outs),
   (ins i32imm:$instid, i32imm:$cpidx, i32imm:$size), "", []>;
+
+include "CSKYInstrInfo16Instr.td"
diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td b/llvm/lib/Target/CSKY/CSKYInstrInfo16Instr.td
new file mode 100644 (file)
index 0000000..c98f436
--- /dev/null
@@ -0,0 +1,452 @@
+//===-- CSKYInstrInfo16Instr.td - CSKY 16-bit Instruction --*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the CSKY 16-bit instructions in TableGen format.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// CSKY specific DAG Nodes.
+//===----------------------------------------------------------------------===//
+
+// Target-dependent nodes.
+def CSKY_NIE : SDNode<"CSKYISD::NIE", SDTNone,
+    [SDNPHasChain, SDNPOptInGlue]>;
+def CSKY_NIR : SDNode<"CSKYISD::NIR", SDTNone,
+    [SDNPHasChain, SDNPOptInGlue]>;
+
+//===----------------------------------------------------------------------===//
+// Operand and SDNode transformation definitions.
+//===----------------------------------------------------------------------===//
+
+def br_symbol_16bit : Operand<iPTR> {
+  let EncoderMethod =
+    "getBranchSymbolOpValue<CSKY::fixup_csky_pcrel_imm10_scale2>";
+  let ParserMatchClass = CSKYSymbol;
+  let DecoderMethod = "decodeSImmOperand<10, 1>";
+  let PrintMethod = "printCSKYSymbolOperand";
+  let OperandType = "OPERAND_PCREL";
+}
+
+def SPOperand : AsmOperandClass {
+  let Name = "SPOperand";
+  let RenderMethod = "addRegOperands";
+  let DiagnosticType = !strconcat("Invalid", Name);
+}
+
+def SPOp : RegisterOperand<GPR> {
+ let ParserMatchClass = SPOperand;
+}
+
+def constpool_symbol_16bit : Operand<iPTR> {
+  let ParserMatchClass = Constpool;
+  let EncoderMethod =
+    "getConstpoolSymbolOpValue<CSKY::fixup_csky_pcrel_uimm7_scale4>";
+  let DecoderMethod = "decodeLRW16Imm8";
+  let PrintMethod = "printConstpool";
+  let OperandType = "OPERAND_PCREL";
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction Formats
+//===----------------------------------------------------------------------===//
+
+include "CSKYInstrFormats16Instr.td"
+
+//===----------------------------------------------------------------------===//
+// Instruction definitions.
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Basic ALU instructions.
+//===----------------------------------------------------------------------===//
+
+let isCommutable = 1, isAdd = 1 in
+  def ADDU16 : R16_XYZ<0, "addu16", add>;
+let Pattern = [(set mGPR:$rz, (sub mGPR:$rx, mGPR:$ry))] in
+  def SUBU16 : R16_XYZ<1, "subu16", sub>;
+
+let isCommutable = 1, isAdd = 1 in
+  def ADDC16 : R16_XZ_BINOP_C<0b1000, 0b01, "addc16">;
+def SUBC16 : R16_XZ_BINOP_C<0b1000, 0b11, "subc16">;
+
+let isCommutable = 1 in {
+  let isAdd = 1 in
+  def ADDU16XZ : R16_XZ_BINOP<0b1000, 0b00, "addu16", BinOpFrag<(add node:$LHS, node:$RHS)>>;
+  def AND16 : R16_XZ_BINOP<0b1010, 0b00, "and16", BinOpFrag<(and node:$LHS, node:$RHS)>>;
+  def OR16 : R16_XZ_BINOP<0b1011, 0b00, "or16", BinOpFrag<(or node:$LHS, node:$RHS)>>;
+  def XOR16 : R16_XZ_BINOP<0b1011, 0b01, "xor16", BinOpFrag<(xor node:$LHS, node:$RHS)>>;
+  def NOR16 : R16_XZ_BINOP<0b1011, 0b10, "nor16", BinOpFrag<(not (or node:$LHS, node:$RHS))>>;
+  let isCodeGenOnly = 1 in
+  def NOT16 : R16_XZ_UNOP<0b1011, 0b10, "not16">;
+  def MULT16 :  R16_XZ_BINOP<0b1111, 0b00, "mult16", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
+}
+def SUBU16XZ : R16_XZ_BINOP<0b1000, 0b10, "subu16", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
+def ANDN16 : R16_XZ_BINOP<0b1010, 0b01, "andn16", BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
+def LSL16 : R16_XZ_BINOP<0b1100, 0b00, "lsl16", BinOpFrag<(shl node:$LHS, node:$RHS)>>;
+def LSR16 : R16_XZ_BINOP<0b1100, 0b01, "lsr16", BinOpFrag<(srl node:$LHS, node:$RHS)>>;
+def ASR16 : R16_XZ_BINOP<0b1100, 0b10, "asr16", BinOpFrag<(sra node:$LHS, node:$RHS)>>;
+def ROTL16 : R16_XZ_BINOP<0b1100, 0b11, "rotl16", BinOpFrag<(rotl node:$LHS, (and node:$RHS, 0x1f))>>;
+
+def MULSH16 : R16_XZ_BINOP_NOPat<0b1111, 0b01, "mulsh16">;
+
+def ZEXTB16 : R16_XZ_UNOP<0b1101, 0b00, "zextb16">;
+def ZEXTH16 : R16_XZ_UNOP<0b1101, 0b01, "zexth16">;
+def SEXTB16 : R16_XZ_UNOP<0b1101, 0b10, "sextb16">;
+def SEXTH16 : R16_XZ_UNOP<0b1101, 0b11, "sexth16">;
+
+let Constraints = "$rZ = $rz", isReMaterializable = 1, isAsCheapAsAMove = 1 in {
+  let isAdd = 1, Pattern = [(set mGPR:$rz, (add mGPR:$rZ, oimm8:$imm8))] in
+  def ADDI16 : I16_Z_8<0b100, (ins mGPR:$rZ, oimm8:$imm8), "addi16\t$rz, $imm8">;
+  let Pattern = [(set mGPR:$rz, (sub mGPR:$rZ, oimm8:$imm8))] in
+  def SUBI16 : I16_Z_8<0b101, (ins mGPR:$rZ, oimm8:$imm8), "subi16\t$rz, $imm8">;
+}
+
+let isAdd = 1 in
+def ADDI16ZSP : I16_Z_8<0b011, (ins SPOp:$sp, uimm8_2:$imm8),
+                        "addi16\t$rz, $sp, $imm8">;
+
+let isAdd = 1 in
+def ADDI16SPSP : I16_SP_IMM7<0b000,"addi16">;
+def SUBI16SPSP : I16_SP_IMM7<0b001,"subi16">;
+
+let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
+  def LSLI16 : I16_XZ_IMM5<0, "lsli16", shl>;
+  def LSRI16 : I16_XZ_IMM5<1, "lsri16", srl>;
+  def ASRI16 : I16_XZ_IMM5<2, "asri16", sra>;
+}
+
+let isAdd = 1 in
+def ADDI16XZ : I16_XZ_IMM3<0b10, "addi16", add>;
+def SUBI16XZ : I16_XZ_IMM3<0b11, "subi16", sub>;
+
+let Size = 4 in
+def NEG16 : CSKYPseudo<(outs mGPR:$rd), (ins mGPR:$rx), "neg16 $rd, $rx", []>;
+
+let Size = 4 in
+def RSUBI16 : CSKYPseudo<(outs mGPR:$rd),
+  (ins mGPR:$rx, uimm8:$imm8), "rsubi16 $rd, $rx, $imm8", []>;
+
+//===----------------------------------------------------------------------===//
+// Load & Store instructions.
+//===----------------------------------------------------------------------===//
+
+def LD16B : I16_XZ_LDST<AddrMode16B, 0b000, "ld16.b",
+  (outs mGPR:$rz), (ins mGPR:$rx, uimm5:$imm)>;
+def LD16H : I16_XZ_LDST<AddrMode16H, 0b001, "ld16.h",
+  (outs mGPR:$rz), (ins mGPR:$rx, uimm5_1:$imm)>;
+def LD16W : I16_XZ_LDST<AddrMode16W, 0b010, "ld16.w",
+  (outs mGPR:$rz), (ins mGPR:$rx, uimm5_2:$imm)>;
+def ST16B : I16_XZ_LDST<AddrMode16B, 0b100, "st16.b",
+  (outs), (ins mGPR:$rz, mGPR:$rx, uimm5:$imm)>;
+def ST16H : I16_XZ_LDST<AddrMode16H, 0b101, "st16.h",
+  (outs), (ins mGPR:$rz, mGPR:$rx, uimm5_1:$imm)>;
+def ST16W : I16_XZ_LDST<AddrMode16W, 0b110, "st16.w",
+  (outs), (ins mGPR:$rz, mGPR:$rx, uimm5_2:$imm)>;
+
+def LD16WSP : I16_ZSP_LDST<AddrMode16W, 0b011, "ld16.w",
+  (outs mGPR:$rz), (ins SPOp:$sp, uimm8_2:$addr)>;
+def ST16WSP : I16_ZSP_LDST<AddrMode16W, 0b111, "st16.w",
+  (outs), (ins mGPR:$rz, SPOp:$sp, uimm8_2:$addr)>;
+
+//===----------------------------------------------------------------------===//
+// Compare instructions.
+//===----------------------------------------------------------------------===//
+
+def CMPHS16 : R16_XY_CMP<0, "cmphs16">;
+def CMPLT16 : R16_XY_CMP<1, "cmplt16">;
+let isCommutable = 1 in
+def CMPNE16 : R16_XY_CMP<2, "cmpne16">;
+
+
+def CMPHSI16 : I16_X_CMP<0, "cmphsi16", oimm5>;
+def CMPLTI16 : I16_X_CMP<1, "cmplti16", oimm5>;
+def CMPLEI16 : CSKYPseudo<(outs CARRY:$ca), (ins mGPR:$rx, uimm5:$imm5),
+    "cmplei16\t$rx, $imm5", []>;
+def CMPNEI16 : I16_X_CMP<2, "cmpnei16", uimm5>;
+
+//===----------------------------------------------------------------------===//
+// Data move instructions.
+//===----------------------------------------------------------------------===//
+
+
+def MOVI16 : I16_Z_8<0b110, (ins uimm8:$imm8), "movi16\t$rz, $imm8"> {
+  let isReMaterializable = 1;
+  let isAsCheapAsAMove = 1;
+  let isMoveImm = 1;
+  let Pattern = [(set mGPR:$rz, uimm8:$imm8)];
+}
+
+def MOV16 : CSKY16Inst<AddrModeNone, (outs sGPR:$rz), (ins sGPR:$rx),
+                       "mov16\t$rz, $rx", []> {
+  bits<4> rz;
+  bits<4> rx;
+  let Inst{15,14} = 0b01;
+  let Inst{13 - 10} = 0b1011;
+  let Inst{9 - 6} = rz;
+  let Inst{5 - 2} = rx;
+  let Inst{1,0} = 0b11;
+}
+
+// MVC16 is not in "cskyv2 instructions reference manul"
+def MVCV16 : CSKY16Inst<AddrModeNone,
+  (outs sGPR:$rz), (ins CARRY:$ca), "mvcv16\t$rz", []> {
+  bits<4> rz;
+  let Inst{15,14} = 0b01;
+  let Inst{13 - 10} = 0b1001;
+  let Inst{9 - 6} = rz;
+  let Inst{5 - 2} = 0;
+  let Inst{1,0} = 0b11;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Branch and call instructions.
+//===----------------------------------------------------------------------===//
+
+let isBranch = 1, isTerminator = 1 in {
+  let isBarrier = 1, isPredicable = 1 in
+    def BR16 : J16<1, "br16", (ins br_symbol_16bit:$offset)>;
+
+  def BT16 : J16_B<2, "bt16">;
+  def BF16 : J16_B<3, "bf16">;
+}
+
+def JMP16 : R16_X_J<0b11100000, 0b00, "jmp16"> {
+  let isBranch = 1;
+  let isTerminator = 1;
+  let isBarrier = 1;
+  let isIndirectBranch = 1;
+  let Pattern = [(brind sGPR:$rx)];
+}
+
+def JSR16 : R16_X_J<0b11101111, 0b01, "jsr16"> {
+  let isCall = 1;
+  let Defs = [ R15 ];
+}
+
+def RTS16 : CSKY16Inst<AddrModeNone, (outs), (ins), "rts16", [(CSKY_RET)]> {
+  let isTerminator = 1;
+  let isReturn = 1;
+  let isBarrier = 1;
+  let Inst = 0b0111100000111100;
+  let Uses = [R15];
+  let isCodeGenOnly = 1;
+}
+
+def JMPIX16 :  CSKY16Inst<AddrModeNone, (outs),
+  (ins mGPR:$rx, uimm2_jmpix:$indeximm2), "jmpix16\t$rx, $indeximm2", []> {
+  bits<3> rx;
+  bits<2> indeximm2;
+  let Inst{15,14} = 0b00;
+  let Inst{13 - 11} = 0b111;
+  let Inst{10 - 8} = rx;
+  let Inst{7 - 2} = 0b111000;
+  let Inst{1,0} = indeximm2;
+  let Predicates = [HasJAVA];
+  let Uses = [R30];
+}
+
+//===----------------------------------------------------------------------===//
+// Symbol address instructions.
+//===----------------------------------------------------------------------===//
+
+def LRW16 : CSKY16Inst<AddrModeNone, (outs mGPR:$rz),
+  (ins constpool_symbol_16bit:$label), "lrw16\t$rz, $label", []> {
+  bits<3> rz;
+  bits<8> label;
+  let Inst{15 - 13} = 0b000;
+  let Inst{12} = label{7};
+  let Inst{11,10} = 0b00;
+  let Inst{9,8} = label{6,5};
+  let Inst{7 - 5} = rz;
+  let Inst{4 - 0} = label{4-0};
+  let mayLoad = 1;
+  let mayStore = 0;
+}
+
+def LRW16_Gen : CSKY16Inst<AddrModeNone, (outs mGPR:$rz),
+  (ins bare_symbol:$src, constpool_symbol_16bit:$label),
+  "lrw16\t$rz, $label", []> {
+  bits<3> rz;
+  bits<8> label;
+  let Inst{15 - 13} = 0b000;
+  let Inst{12} = label{7};
+  let Inst{11,10} = 0b00;
+  let Inst{9,8} = label{6,5};
+  let Inst{7 - 5} = rz;
+  let Inst{4 - 0} = label{4-0};
+  let mayLoad = 1;
+  let mayStore = 0;
+  let isCodeGenOnly = 1;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Other operation instructions.
+//===----------------------------------------------------------------------===//
+
+def REVB16 :  R16_XZ_UNOP<0b1110, 0b10, "revb16">;
+def REVH16 :  R16_XZ_UNOP<0b1110, 0b11, "revh16">;
+
+let isCodeGenOnly = 1 in
+def SETC16 : CSKY16Inst<AddrModeNone,
+  (outs CARRY:$ca), (ins), "setc16", []> {
+  let Inst{15, 14} = 0b01;
+  let Inst{13 - 10} = 0b1001;
+  let Inst{9 - 6} = 0;
+  let Inst{5 - 2} = 0;
+  let Inst{1, 0} = 0;
+  let isCompare = 1;
+}
+
+let isCodeGenOnly = 1 in
+def CLRC16 : CSKY16Inst<AddrModeNone,
+  (outs CARRY:$ca), (ins), "clrc16", []> {
+  let Inst{15, 14} = 0b01;
+  let Inst{13 - 10} = 0b1001;
+  let Inst{9 - 6} = 0;
+  let Inst{5 - 2} = 0;
+  let Inst{1, 0} = 2;
+  let isCompare = 1;
+}
+
+let Constraints = "$rZ = $rz" in {
+  def BCLRI16 : I16_Z_5<0b100, (outs mGPR:$rz), (ins mGPR:$rZ, uimm5:$imm5),
+                        "bclri16">;
+  def BSETI16 : I16_Z_5<0b101, (outs mGPR:$rz), (ins mGPR:$rZ, uimm5:$imm5),
+                        "bseti16">;
+}
+
+let Predicates = [HasBTST16] in
+  def BTSTI16 : I16_Z_5<0b110, (outs CARRY:$ca), (ins mGPR:$rz, uimm5:$imm5),
+                        "btsti16">;
+
+def TST16 : CSKY16Inst<AddrModeNone, (outs CARRY:$ca), (ins sGPR:$rx, sGPR:$ry),
+                        "tst16\t$rx, $ry", []> {
+  bits<4> ry;
+  bits<4> rx;
+  let Inst{15,14} = 0b01;
+  let Inst{13 - 10} = 0b1010;
+  let Inst{9 - 6} = ry;
+  let Inst{5 - 2} = rx;
+  let Inst{1,0} = 0b10;
+  let isCompare = 1;
+}
+
+def TSTNBZ16 : CSKY16Inst<AddrModeNone, (outs CARRY:$ca), (ins sGPR:$rx),
+                          "tstnbz16\t$rx", []> {
+  bits<4> rx;
+  let Inst{15,14} = 0b01;
+  let Inst{13 - 10} = 0b1010;
+  let Inst{9 - 6} = 0b0000;
+  let Inst{5 - 2} = rx;
+  let Inst{1,0} = 0b11;
+  let isCompare = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// Special instructions.
+//===----------------------------------------------------------------------===//
+
+def BKPT : CSKY16Inst<AddrModeNone, (outs), (ins), "bkpt", []> {
+  let Inst = 0;
+}
+
+let mayStore = 1 in {
+def BPUSHH : I16_BPushPop<0b00010100111, 0, (outs), (ins mGPR:$rz), "bpush.h $rz">;
+def BPUSHW : I16_BPushPop<0b00010100111, 0b10, (outs), (ins mGPR:$rz), "bpush.w $rz">;
+}
+
+let mayLoad = 1 in {
+def BPOPH : I16_BPushPop<0b00010100101, 0, (outs mGPR:$rz), (ins),  "bpop.h $rz">;
+def BPOPW : I16_BPushPop<0b00010100101, 0b10, (outs mGPR:$rz), (ins), "bpop.w $rz">;
+}
+
+def NIE : CSKY16Inst<AddrModeNone, (outs), (ins), "nie", [(CSKY_NIE)]> {
+  let Inst = 0b0001010001100000;
+}
+
+let isBarrier = 1, isReturn = 1, isTerminator = 1 in
+def NIR : CSKY16Inst<AddrModeNone, (outs), (ins), "nir", [(CSKY_NIR)]> {
+  let Inst = 0b0001010001100001;
+}
+
+def IPUSH16 : CSKY16Inst<AddrModeNone, (outs), (ins), "ipush16", []> {
+  let Inst{15- 5} = 0b00010100011;
+  let Inst{4-0} = 0b00010;
+  let Predicates = [iHasE1];
+  let Defs  = [R14];
+  let Uses  = [R14, R0, R1, R2, R3, R12, R13];
+  let mayStore = 1;
+}
+
+def IPOP16 : CSKY16Inst<AddrModeNone, (outs), (ins), "ipop16", []> {
+  let Inst{15- 5} = 0b00010100011;
+  let Inst{4-0} = 0b00011;
+  let Predicates = [iHasE1];
+  let Defs  = [R14, R0, R1, R2, R3, R12, R13];
+  let Uses  = [R14];
+  let mayLoad = 1;
+}
+
+def PUSH16 : CSKY16Inst<AddrModeNone, (outs),
+  (ins reglist:$regs, variable_ops), "push16 $regs", []> {
+  bits<5> regs;
+
+  let Inst{15- 5} = 0b00010100110;
+  let Inst{4-0} = regs;
+  let Predicates = [iHasE1];
+  let Defs  = [R14];
+  let Uses  = [R14];
+  let mayStore = 1;
+}
+
+def POP16 : CSKY16Inst<AddrModeNone, (outs),
+  (ins reglist:$regs, variable_ops), "pop16 $regs", []> {
+  bits<5> regs;
+
+  let Inst{15- 5} = 0b00010100100;
+  let Inst{4-0} = regs;
+  let Predicates = [iHasE1];
+  let Defs  = [R14];
+  let Uses  = [R14];
+  let mayLoad = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// CSKYPseudo
+//===----------------------------------------------------------------------===//
+
+let usesCustomInserter = 1 in  {
+  def ISEL16 : CSKYPseudo<(outs sGPR:$dst),
+    (ins CARRY:$cond, sGPR:$src1, sGPR:$src2),
+    "!isel16\t$dst, $src1, src2",
+    [(set sGPR:$dst, (select CARRY:$cond, sGPR:$src1, sGPR:$src2))]>;
+}
+
+class JBranchPseudo<dag out, dag ins, string opstr> :
+  CSKYPseudo<out, ins, opstr, []> {
+  let isBranch = 1;
+  let isTerminator = 1;
+  let isIndirectBranch = 1;
+  let mayLoad = 1;
+  let Size = 2;
+}
+
+let isBarrier = 1 in
+def JBR16 : JBranchPseudo<(outs),
+  (ins br_symbol_16bit:$src1), "jbr16\t$src1">;
+def JBT16 : JBranchPseudo<(outs),
+  (ins CARRY:$ca, br_symbol_16bit:$src1), "jbt16\t$src1">;
+def JBF16 : JBranchPseudo<(outs),
+  (ins CARRY:$ca, br_symbol_16bit:$src1), "jbf16\t$src1">;
+
+let mayLoad = 1, Size = 2, isCodeGenOnly = 0 in
+def PseudoLRW16 : CSKYPseudo<(outs mGPR:$rz),
+  (ins bare_symbol:$src), "lrw16 $rz, $src", []>;
index aef4589..7548c22 100644 (file)
@@ -153,6 +153,21 @@ def GPR : RegisterClass<"CSKY", [i32], 32,
   let Size = 32;
 }
 
+// Register class for R0 - R15.
+// Some 16-bit integer instructions can only access R0 - R15.
+def sGPR : RegisterClass<"CSKY", [i32], 32,
+                        (add (sequence "R%u", 0, 3), (sequence "R%u", 12, 13), R15,
+                        (sequence "R%u", 4, 11), R14)> {
+  let Size = 32;
+}
+
+// Register class for R0 - R7.
+// Some 16-bit integer instructions can only access R0 - R7.
+def mGPR : RegisterClass<"CSKY", [i32], 32,
+                        (add (sequence "R%u", 0, 7))> {
+  let Size = 32;
+}
+
 def GPRPair : RegisterClass<"CSKY", [untyped], 32, (add GPRTuple)> {
   let Size = 64;
 }
index dc0d2c4..963c2ed 100644 (file)
@@ -36,6 +36,8 @@ CSKYSubtarget &CSKYSubtarget::initializeSubtargetDependencies(
   HasFPUv3SingleFloat = false;
   HasFPUv3DoubleFloat = false;
 
+  HasBTST16 = false;
+  HasJAVA = false;
   HasExtendLrw = false;
   HasDoloop = false;
   HasHighRegisters = false;
@@ -70,4 +72,3 @@ bool CSKYSubtarget::useHardFloatABI() const {
   else
     return FloatABI == FloatABI::Hard;
 }
-
index ece9450..4cd590e 100644 (file)
@@ -43,6 +43,8 @@ class CSKYSubtarget : public CSKYGenSubtargetInfo {
   bool HasFPUv3SingleFloat;
   bool HasFPUv3DoubleFloat;
 
+  bool HasBTST16;
+  bool HasJAVA;
   bool HasExtendLrw;
   bool HasDoloop;
   bool HasHighRegisters;
@@ -95,6 +97,8 @@ public:
   bool hasFPUv3() const { return HasFPUv3SingleFloat || HasFPUv3DoubleFloat; }
   bool hasAnyFloatExt() const { return hasFPUv2() || hasFPUv3(); };
 
+  bool hasBTST16() const { return HasBTST16; }
+  bool hasJAVA() const { return HasJAVA; }
   bool hasExtendLrw() const { return HasExtendLrw; }
   bool hasDoloop() const { return HasDoloop; }
   bool hasHighRegisters() const { return HasHighRegisters; }
index 3c88344..ecb9fe9 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef LLVM_LIB_TARGET_CSKY_CSKYTARGETMACHINE_H
 #define LLVM_LIB_TARGET_CSKY_CSKYTARGETMACHINE_H
 
+#include "CSKYSubtarget.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/Target/TargetMachine.h"
 
diff --git a/llvm/test/MC/CSKY/basic-16bit.s b/llvm/test/MC/CSKY/basic-16bit.s
new file mode 100644 (file)
index 0000000..9b48443
--- /dev/null
@@ -0,0 +1,270 @@
+# RUN: llvm-mc %s -triple=csky -show-encoding -csky-no-aliases -mattr=+e1 \
+# RUN: -mattr=+e2 -mattr=+btst16 | FileCheck -check-prefixes=CHECK-ASM %s
+
+# CHECK-ASM: addi16 a0, a0, 2
+# CHECK-ASM: encoding: [0x06,0x58]
+addi16 a0, a0, 2
+
+# CHECK-ASM: addi16 a0, sp, 4
+# CHECK-ASM: encoding: [0x01,0x18]
+addi16 a0, sp, 4
+
+# CHECK-ASM: addi16 a0, a1, 2
+# CHECK-ASM: encoding: [0x06,0x59]
+addi16 a0, a1, 2
+
+# CHECK-ASM: addi16 sp, sp, 8
+# CHECK-ASM: encoding: [0x02,0x14]
+addi16 sp, sp, 8
+
+# CHECK-ASM: subi16 a0, a0, 2
+# CHECK-ASM: encoding: [0x07,0x58]
+subi16 a0, a0, 2
+
+# CHECK-ASM: subi16 a0, a1, 2
+# CHECK-ASM: encoding: [0x07,0x59]
+subi16 a0, a1, 2
+
+# CHECK-ASM: subi16 sp, sp, 8
+# CHECK-ASM: encoding: [0x22,0x14]
+subi16 sp, sp, 8
+
+# CHECK-ASM: lsli16 a0, a1, 2
+# CHECK-ASM: encoding: [0x02,0x41]
+lsli16 a0, a1, 2
+
+# CHECK-ASM: lsri16 a0, a1, 2
+# CHECK-ASM: encoding: [0x02,0x49]
+lsri16 a0, a1, 2
+
+# CHECK-ASM: asri16 a0, a1, 2
+# CHECK-ASM: encoding: [0x02,0x51]
+asri16 a0, a1, 2
+
+# CHECK-ASM: btsti16 a0, 2
+# CHECK-ASM: encoding: [0xc2,0x38]
+btsti16 a0, 2
+
+# CHECK-ASM: bclri16 a0, 2
+# CHECK-ASM: encoding: [0x82,0x38]
+bclri16 a0, 2
+
+# CHECK-ASM: bseti16 a0, 2
+# CHECK-ASM: encoding: [0xa2,0x38]
+bseti16 a0, 2
+
+# CHECK-ASM: cmpnei16 a0, 2
+# CHECK-ASM: encoding: [0x42,0x38]
+cmpnei16 a0, 2
+
+# CHECK-ASM: cmphsi16 a0, 2
+# CHECK-ASM: encoding: [0x01,0x38]
+cmphsi16 a0, 2
+
+# CHECK-ASM: cmplti16 a0, 2
+# CHECK-ASM: encoding: [0x21,0x38]
+cmplti16 a0, 2
+
+# CHECK-ASM: movi16 a0, 2
+# CHECK-ASM: encoding: [0x02,0x30]
+movi16 a0, 2
+
+# CHECK-ASM: addu16 a3, l0, l1
+# CHECK-ASM: encoding: [0x74,0x5c]
+addu16 a3, l0, l1
+
+# CHECK-ASM: subu16 a3, l0, l1
+# CHECK-ASM: encoding: [0x75,0x5c]
+subu16 a3, l0, l1
+
+# CHECK-ASM: and16 a3, l0
+# CHECK-ASM: encoding: [0xd0,0x68]
+and16 a3, l0
+
+# CHECK-ASM: andn16 a3, l0
+# CHECK-ASM: encoding: [0xd1,0x68]
+andn16 a3, l0
+
+# CHECK-ASM: or16 a3, l0
+# CHECK-ASM: encoding: [0xd0,0x6c]
+or16 a3, l0
+
+# CHECK-ASM: xor16 a3, l0
+# CHECK-ASM: encoding: [0xd1,0x6c]
+xor16 a3, l0
+
+# CHECK-ASM: nor16 a3, l0
+# CHECK-ASM: encoding: [0xd2,0x6c]
+nor16 a3, l0
+
+# CHECK-ASM: lsl16 a3, l0
+# CHECK-ASM: encoding: [0xd0,0x70]
+lsl16 a3, l0
+
+# CHECK-ASM: rotl16 a3, l0
+# CHECK-ASM: encoding: [0xd3,0x70]
+rotl16 a3, l0
+
+# CHECK-ASM: lsr16 a3, l0
+# CHECK-ASM: encoding: [0xd1,0x70]
+lsr16 a3, l0
+
+# CHECK-ASM: asr16 a3, l0
+# CHECK-ASM: encoding: [0xd2,0x70]
+asr16 a3, l0
+
+# CHECK-ASM: mult16 a3, l0
+# CHECK-ASM: encoding: [0xd0,0x7c]
+mult16 a3, l0
+
+# CHECK-ASM: addc16 a3, l0
+# CHECK-ASM: encoding: [0xd1,0x60]
+addc16 a3, l0
+
+# CHECK-ASM: subc16 a3, l0
+# CHECK-ASM: encoding: [0xd3,0x60]
+subc16 a3, l0
+
+# CHECK-ASM: ld16.b a0, (a0, 2)
+# CHECK-ASM: encoding: [0x02,0x80]
+ld16.b a0, (a0, 2)
+
+# CHECK-ASM: ld16.h a0, (a0, 2)
+# CHECK-ASM: encoding: [0x01,0x88]
+ld16.h a0, (a0, 2)
+
+# CHECK-ASM: ld16.w a0, (a0, 4)
+# CHECK-ASM: encoding: [0x01,0x90]
+ld16.w a0, (a0, 4)
+
+# CHECK-ASM: ld16.w a0, (sp, 4)
+# CHECK-ASM: encoding: [0x01,0x98]
+ld16.w a0, (sp, 4)
+
+# CHECK-ASM: st16.b a0, (a0, 2)
+# CHECK-ASM: encoding: [0x02,0xa0]
+st16.b a0, (a0, 2)
+
+# CHECK-ASM: st16.h a0, (a0, 2)
+# CHECK-ASM: encoding: [0x01,0xa8]
+st16.h a0, (a0, 2)
+
+# CHECK-ASM: st16.w a0, (a0, 4)
+# CHECK-ASM: encoding: [0x01,0xb0]
+st16.w a0, (a0, 4)
+
+# CHECK-ASM: st16.w a0, (sp, 4)
+# CHECK-ASM: encoding: [0x01,0xb8]
+st16.w a0, (sp, 4)
+
+# CHECK-ASM: revb16 a3, l0
+# CHECK-ASM: encoding: [0xd2,0x78]
+revb16 a3, l0
+
+# CHECK-ASM: revh16 a3, l0
+# CHECK-ASM: encoding: [0xd3,0x78]
+revh16 a3, l0
+
+# CHECK-ASM: mvcv16 a3
+# CHECK-ASM: encoding: [0xc3,0x64]
+mvcv16 a3
+
+# CHECK-ASM: cmpne16 a3, l0
+# CHECK-ASM: encoding: [0x0e,0x65]
+cmpne16 a3, l0
+
+# CHECK-ASM: cmphs16 a3, l0
+# CHECK-ASM: encoding: [0x0c,0x65]
+cmphs16 a3, l0
+
+# CHECK-ASM: cmplt16 a3, l0
+# CHECK-ASM: encoding: [0x0d,0x65]
+cmplt16 a3, l0
+
+# CHECK-ASM: tst16 a3, l0
+# CHECK-ASM: encoding: [0x0e,0x69]
+tst16 a3, l0
+
+# CHECK-ASM: tstnbz16 a3
+# CHECK-ASM: encoding: [0x0f,0x68]
+tstnbz16 a3
+
+# CHECK-ASM: br16 .L.test
+# CHECK-ASM: encoding: [A,0x04'A']
+# CHECK-ASM: fixup A - offset: 0, value: .L.test, kind: fixup_csky_pcrel_imm10_scale2
+.L.test:
+br16 .L.test
+
+# CHECK-ASM: bt16 .L.test2
+# CHECK-ASM: encoding: [A,0x08'A']
+# CHECK-ASM: fixup A - offset: 0, value: .L.test2, kind: fixup_csky_pcrel_imm10_scale2
+.L.test2:
+bt16 .L.test2
+
+# CHECK-ASM: bf16 .L.test3
+# CHECK-ASM: encoding: [A,0x0c'A']
+# CHECK-ASM: fixup A - offset: 0, value: .L.test3, kind: fixup_csky_pcrel_imm10_scale2
+.L.test3:
+bf16 .L.test3
+
+# CHECK-ASM: jmp16 a3
+# CHECK-ASM: encoding: [0x0c,0x78]
+jmp16 a3
+
+# CHECK-ASM: jsr16 a3
+# CHECK-ASM: encoding: [0xcd,0x7b]
+jsr16 a3
+
+# CHECK-ASM: lrw16 a0, [.L.test14]
+# CHECK-ASM: encoding: [A,A]
+# CHECK-ASM: fixup A - offset: 0, value: .L.test14, kind: fixup_csky_pcrel_uimm7_scale4
+.L.test14:
+lrw16 a0, [.L.test14]
+
+# RUN: not llvm-mc -triple csky -mattr=+e1 -mattr=+e2 -mattr=+btst16 --defsym=ERR=1 < %s 2>&1 | FileCheck %s
+
+.ifdef ERR
+
+# oimm8
+addi16 a0, 0 # CHECK: :[[#@LINE]]:12: error: operand must be sp register
+
+# oimm5
+cmphsi16 a0, 0 # CHECK: :[[#@LINE]]:14: error: immediate must be an integer in the range [1, 32]
+
+# uimm5
+lsli16 a0, a0, 32 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [0, 31]
+
+# uimm5/uimm5_1/uimm5_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]
+
+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]
+
+# Invalid mnemonics
+subs t0, t2, t1 # CHECK: :[[#@LINE]]:1: error: unrecognized instruction mnemonic
+nandi t0, t2, 0 # CHECK: :[[#@LINE]]:1: error: unrecognized instruction mnemonic
+
+# Invalid register names
+addi16 foo, sp, 10 # CHECK: :[[#@LINE]]:8: error: unknown operand
+lsli16 a10, a2, 0x20 # CHECK: :[[#@LINE]]:8: error: unknown operand
+asri16 x16, s0, s0 # CHECK: :[[#@LINE]]:8: error: unknown operand
+
+# Invalid operand types
+lsli16 a0, 22, 220 # CHECK: :[[#@LINE]]:12: error: invalid operand for instruction
+subu16 a0, a1, 1 # CHECK: :[[#@LINE]]:16: error: invalid operand for instruction
+
+# Too many operands
+lsli16 a0, a1, 0x11, 0x60 # CHECK: :[[@LINE]]:22: error: invalid operand for instruction
+
+# Too few operands
+lsli16 a0 # CHECK: :[[#@LINE]]:1: error: too few operands for instruction
+lsl16 a0  # CHECK: :[[#@LINE]]:1: error: too few operands for instruction
+
+.endif
\ No newline at end of file