diff options
author | 2021-04-20 14:40:46 +0800 | |
---|---|---|
committer | 2021-04-20 15:36:49 +0800 | |
commit | 4216389c2653064bd5503780ce29c010d857b278 (patch) | |
tree | fbcc10302d93ddace709400944bd3a54455c0279 | |
parent | [CSKY 4/n] Add basic CSKYAsmParser and CSKYInstPrinter (diff) | |
download | llvm-project-4216389c2653064bd5503780ce29c010d857b278.tar.gz llvm-project-4216389c2653064bd5503780ce29c010d857b278.tar.bz2 llvm-project-4216389c2653064bd5503780ce29c010d857b278.zip |
[CSKY 5/n] Add support for all CSKY basic integer instructions except for branch series
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
-rw-r--r-- | llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp | 92 | ||||
-rw-r--r-- | llvm/lib/Target/CSKY/CSKYInstrFormats.td | 59 | ||||
-rw-r--r-- | llvm/lib/Target/CSKY/CSKYInstrInfo.td | 110 | ||||
-rw-r--r-- | llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h | 8 | ||||
-rw-r--r-- | llvm/test/MC/CSKY/basic.s | 184 |
5 files changed, 407 insertions, 46 deletions
diff --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp index 718b14cc523f..c971638e449c 100644 --- a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp +++ b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp @@ -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; diff --git a/llvm/lib/Target/CSKY/CSKYInstrFormats.td b/llvm/lib/Target/CSKY/CSKYInstrFormats.td index 86f9dd0b7da3..bc247eecfd70 100644 --- a/llvm/lib/Target/CSKY/CSKYInstrFormats.td +++ b/llvm/lib/Target/CSKY/CSKYInstrFormats.td @@ -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 diff --git a/llvm/lib/Target/CSKY/CSKYInstrInfo.td b/llvm/lib/Target/CSKY/CSKYInstrInfo.td index 88985a968c90..a3e5c9c81012 100644 --- a/llvm/lib/Target/CSKY/CSKYInstrInfo.td +++ b/llvm/lib/Target/CSKY/CSKYInstrInfo.td @@ -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">; diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h index c850a4bab745..99a6763e521e 100644 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h @@ -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 diff --git a/llvm/test/MC/CSKY/basic.s b/llvm/test/MC/CSKY/basic.s index 17f6605c240f..71920e7324e1 100644 --- a/llvm/test/MC/CSKY/basic.s +++ b/llvm/test/MC/CSKY/basic.s @@ -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 |