Index: llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp =================================================================== --- llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp +++ llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp @@ -61,6 +61,7 @@ OperandMatchResultTy parseBaseRegImm(OperandVector &Operands); OperandMatchResultTy parseCSKYSymbol(OperandVector &Operands); OperandMatchResultTy parseConstpoolSymbol(OperandVector &Operands); + OperandMatchResultTy parseRegSeq(OperandVector &Operands); bool parseOperand(OperandVector &Operands, StringRef Mnemonic); @@ -84,6 +85,7 @@ enum KindTy { Token, Register, + RegisterSeq, Immediate, } Kind; @@ -95,10 +97,16 @@ const MCExpr *Val; }; + struct RegSeqOp { + unsigned RegNumFrom; + unsigned RegNumTo; + }; + SMLoc StartLoc, EndLoc; union { StringRef Tok; RegOp Reg; + RegSeqOp RegSeq; ImmOp Imm; }; @@ -113,6 +121,9 @@ case Register: Reg = o.Reg; break; + case RegisterSeq: + RegSeq = o.RegSeq; + break; case Immediate: Imm = o.Imm; break; @@ -124,6 +135,7 @@ bool isToken() const override { return Kind == Token; } bool isReg() const override { return Kind == Register; } + bool isRegisterSeq() const { return Kind == RegisterSeq; } bool isImm() const override { return Kind == Immediate; } bool isMem() const override { return false; } @@ -168,6 +180,7 @@ bool isUImm12() const { return isUImm<12>(); } bool isUImm16() const { return isUImm<16>(); } + bool isOImm5() const { return isOImm<5>(); } bool isOImm12() const { return isOImm<12>(); } bool isOImm16() const { return isOImm<16>(); } @@ -188,6 +201,20 @@ return isImm() && !evaluateConstantImm(getImm(), Imm); } + template bool isRegSeq() const { + if (!isRegisterSeq()) + return false; + + std::pair regSeq = getRegSeq(); + + fprintf(stderr, "regSeq = %d, %d\n", regSeq.first, regSeq.second); + + return regSeq.first <= regSeq.second && Min <= regSeq.first && + regSeq.second <= Max; + } + + bool isRegSeqGPR() const { return isRegSeq(); } + /// Gets location of the first token of this operand. SMLoc getStartLoc() const override { return StartLoc; } /// Gets location of the last token of this operand. @@ -198,6 +225,11 @@ return Reg.RegNum; } + std::pair getRegSeq() const { + assert(Kind == RegisterSeq && "Invalid type access!"); + return std::pair(RegSeq.RegNumFrom, RegSeq.RegNumTo); + } + const MCExpr *getImm() const { assert(Kind == Immediate && "Invalid type access!"); return Imm.Val; @@ -216,6 +248,10 @@ case Register: OS << ""; break; + case RegisterSeq: + OS << ""; + break; case Token: OS << "'" << getToken() << "'"; break; @@ -239,6 +275,16 @@ return Op; } + static std::unique_ptr createRegSeq(unsigned RegNoFrom, + unsigned RegNoTo, SMLoc S) { + auto Op = std::make_unique(RegisterSeq); + Op->RegSeq.RegNumFrom = RegNoFrom; + Op->RegSeq.RegNumTo = RegNoTo; + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } + static std::unique_ptr createImm(const MCExpr *Val, SMLoc S, SMLoc E) { auto Op = std::make_unique(Immediate); @@ -266,6 +312,14 @@ assert(N == 1 && "Invalid number of operands!"); addExpr(Inst, getImm()); } + + void addRegSeqOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + auto regSeq = getRegSeq(); + + Inst.addOperand(MCOperand::createReg(regSeq.first)); + Inst.addOperand(MCOperand::createImm(regSeq.second)); + } }; } // end anonymous namespace. @@ -347,6 +401,8 @@ switch (Result) { default: break; + case Match_InvalidOImm5: + return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 5)); case Match_InvalidOImm12: return generateImmOutOfRangeError(Operands, ErrorInfo, 1, (1 << 12)); case Match_InvalidOImm16: @@ -375,6 +431,11 @@ SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); return Error(ErrorLoc, "operand must be a constpool symbol name"); } + case Match_InvalidRegSeq: { + SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc(); + return Error(ErrorLoc, + "operand must be a register sequence like (rN-rM, N<=M)"); + } } llvm_unreachable("Unknown match type detected!"); @@ -442,6 +503,12 @@ return MatchOperand_ParseFail; } + if (getLexer().is(AsmToken::RParen)) { + Operands.push_back(CSKYOperand::createToken(")", getLoc())); + getParser().Lex(); // Eat ')' + return MatchOperand_Success; + } + if (getLexer().isNot(AsmToken::Comma)) { Error(getLoc(), "expected ','"); return MatchOperand_ParseFail; @@ -596,6 +663,34 @@ return MatchOperand_Success; } +OperandMatchResultTy CSKYAsmParser::parseRegSeq(OperandVector &Operands) { + SMLoc S = getLoc(); + + if (parseRegister(Operands) != MatchOperand_Success) + return MatchOperand_ParseFail; + + auto Ry = Operands.back()->getReg(); + Operands.pop_back(); + + if (getLexer().isNot(AsmToken::Minus)) { + Error(getLoc(), "expected '-'"); + return MatchOperand_ParseFail; + } + + getLexer().Lex(); // eat '-' + + if (parseRegister(Operands) != MatchOperand_Success) { + Error(getLoc(), "invalid register"); + return MatchOperand_ParseFail; + } + + auto Rz = Operands.back()->getReg(); + Operands.pop_back(); + + Operands.push_back(CSKYOperand::createRegSeq(Ry, Rz, S)); + return MatchOperand_Success; +} + bool CSKYAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { // First operand is token for instruction. Index: llvm/lib/Target/CSKY/CSKYInstrFormats.td =================================================================== --- llvm/lib/Target/CSKY/CSKYInstrFormats.td +++ llvm/lib/Target/CSKY/CSKYInstrFormats.td @@ -256,7 +256,7 @@ class I_5_ZX sop, bits<5> pcode, string op, ImmLeaf ImmType, list pattern> : CSKY32Inst { bits<5> rz; bits<5> rx; @@ -268,7 +268,6 @@ let Inst{4 - 0} = imm5; let Constraints = "$rz = $false"; } - // Format< OP[6] | IMM[5] | RX[5] | SOP[6] | PCODE[5] | RZ[5]> // Instructions(13): decgt32, declt32, decne32, lsli32, lslc32, lsri32 // lsrc32, asri32, asrc32, rotli32, xsr32, bclri32, bseti32 @@ -288,17 +287,16 @@ // Format< OP[6] | RY[5] | RX[5] | SOP[6] | PCODE[5] | IMM[5]> // Instructions(2): ldm32, (ldq32), stm32, (stq32) -class I_5_YX opcode, dag outs, dag ins, string op, list pattern, - bits<5> imm5> - : CSKY32Inst(imm5), pattern> { +class I_5_YX opcode, bits<6> sop, dag outs, dag ins, string opStr, list pattern> + : CSKY32Inst { + bits<10> regs; bits<5> rx; - bits<5> ry; - let Inst{25 - 21} = ry; // ry + + let Inst{25 - 21} = regs{9 - 5}; // ry let Inst{20 - 16} = rx; - let Inst{15 - 10} = 0b000111; + let Inst{15 - 10} = sop; let Inst{9 - 5} = 0b00001; - let Inst{4 - 0} = imm5{4 - 0}; // imm5 + let Inst{4 - 0} = regs{4 - 0}; // imm5 } // Format< OP[6] | LSB[5] | RX[5] | SOP[6] | MSB[5] | RZ[5]> @@ -317,14 +315,29 @@ let Inst{4 - 0} = rz; } +// 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_U2 sop, bits<5> lsb, bits<5> msb, dag outs, dag ins, + string op, list pattern> + : CSKY32Inst { + bits<5> rx; + bits<5> rz; + let Inst{25 - 21} = lsb; // lsb + let Inst{20 - 16} = rx; + let Inst{15 - 10} = sop; + let Inst{9 - 5} = msb; // msb + let Inst{4 - 0} = rz; +} + // sextb, sexth -class I_5_XZ_US sop, string op, SDNode opnode, - ValueType type> : I_5_XZ_U; +class I_5_XZ_US sop, bits<5> lsb, bits<5> msb, string op, + SDNode opnode, ValueType type> + : I_5_XZ_U2; -class I_5_XZ_UZ sop, string op, int v> - : I_5_XZ_U; +class I_5_XZ_UZ sop, bits<5> lsb, bits<5> msb, string op, int v> + : I_5_XZ_U2; // Format< OP[6] | RZ[5] | RX[5] | SOP[6] | SIZE[5] | LSB[5]> // Instructions(1): ins32 @@ -493,9 +506,8 @@ // Format< OP[6] | 00000[5] | RX[5] | SOP[6] | PCODE[5] | 00000[5] > // Instructions:(1) tstnbz32 -class R_X sop, bits<5> pcode, string op, list pattern> - : CSKY32Inst { +class R_X sop, bits<5> pcode, dag outs, dag ins, string op, list pattern> + : CSKY32Inst { bits<5> rx; let Inst{25 - 21} = 0; let Inst{20 - 16} = rx; @@ -530,3 +542,36 @@ let Inst{4 - 0} = 0; let Constraints = "$rz = $false"; } + +// sync +class I_5_XZ_SYNC sop, bits<5> pcode, string opStr, bits<1> S, bits<1> I> + : CSKY32Inst { + let Inst{25 - 21} = 0; + let Inst{20 - 16} = 0; + let Inst{15 - 10} = sop; + let Inst{9 - 5} = pcode; + let Inst{4 - 0} = 0; + let Inst{25} = S; + let Inst{21} = I; +} + +// Priviledged Instructions +class I_5_XZ_PRIVI sop, bits<5> pcode, string opStr> + : CSKY32Inst { + let Inst{25 - 21} = 0; + let Inst{20 - 16} = 0; + let Inst{15 - 10} = sop; + let Inst{9 - 5} = pcode; + let Inst{4 - 0} = 0; +} + +class BAR sop, string op, bits<1> signed> + : CSKY32Inst { + let Inst{25} = signed; + let Inst{24 - 16} = 0; + let Inst{15 - 5} = 0x421; + let Inst{4 - 0} = sop; + let hasSideEffects = 1; + let mayLoad = 0; + let mayStore = 0; +} Index: llvm/lib/Target/CSKY/CSKYInstrInfo.td =================================================================== --- llvm/lib/Target/CSKY/CSKYInstrInfo.td +++ llvm/lib/Target/CSKY/CSKYInstrInfo.td @@ -119,6 +119,7 @@ let EncoderMethod = "getBareSymbolOpValue"; } +def oimm5 : oimm<5>; def oimm12 : oimm<12>; def oimm16 : oimm<16>; @@ -131,6 +132,22 @@ def uimm16 : uimm<16>; +class RegSeq : AsmOperandClass { + let Name = "RegSeq" # suffix; + let RenderMethod = "addRegSeqOperands"; + let DiagnosticType = "InvalidRegSeq"; + let ParserMethod = "parseRegSeq"; +} + +class regseq_t : Operand { + let MIOperandInfo = (ops regtype:$ry, uimm5:$imm); + let ParserMatchClass = RegSeq; + let EncoderMethod = "getRegSeqImmOpValue"; + let PrintMethod = "printRegSeq"; +} + +def regseq : regseq_t; + //===----------------------------------------------------------------------===// // Instruction Formats //===----------------------------------------------------------------------===// @@ -150,7 +167,7 @@ //===----------------------------------------------------------------------===// // Basic ALU instructions. //===----------------------------------------------------------------------===// - + let isAdd = 1 in def ADDI32 : I_12<0x0, "addi32", add, oimm12>; def SUBI32 : I_12<0x1, "subi32", sub, oimm12>; def ORI32 : I_16_ZX<"ori32", uimm16, @@ -171,7 +188,7 @@ (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5), [(set GPR:$rz, (rotl GPR:$rx, uimm5:$imm5))]>; - + let isAdd = 1 in def ADDU32 : R_YXZ_SP_F1<0x0, 0x1, BinOpFrag<(add node:$LHS, node:$RHS)>, "addu32", 1>; def SUBU32 : R_YXZ_SP_F1<0x0, 0x4, @@ -188,6 +205,7 @@ BinOpFrag<(xor node:$LHS, node:$RHS)>, "xor32", 1>; def NOR32 : R_YXZ_SP_F1<0x9, 0x4, BinOpFrag<(not (or node:$LHS, node:$RHS))>, "nor32", 1>; + def NOT32 : R_XXZ<0b001001, 0b00100, (outs GPR:$rz), (ins GPR:$rx), "not32", [(set GPR:$rz, (not GPR:$rx))]>; def LSL32 : R_YXZ_SP_F1<0x10, 0x1, @@ -199,7 +217,14 @@ def ROTL32 : R_YXZ_SP_F1<0x10, 0x8, BinOpFrag<(rotl node:$LHS, (and node:$RHS, 0x1f))>, "rotl32">; - // TODO: Shift series instr. with carry. + def LSLC32 : I_5_XZ<0x13, 0x1, "lslc32", + (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, oimm5:$imm5), []>; + def LSRC32 : I_5_XZ<0x13, 0x2, "lsrc32", + (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, oimm5:$imm5), []>; + def ASRC32 : I_5_XZ<0x13, 0x4, "asrc32", + (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, oimm5:$imm5), []>; + def XSR32 : I_5_XZ<0x13, 0x8, "xsr32", + (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, oimm5:$imm5, CARRY:$cin), []>; def IXH32 : R_YXZ_SP_F1<0x2, 0x1, BinOpFrag<(add node:$LHS, (shl node:$RHS, (i32 1)))>, "ixh32">; @@ -209,13 +234,18 @@ def IXD32 : R_YXZ_SP_F1<0x2, 0x4, BinOpFrag<(add node:$LHS, (shl node:$RHS, (i32 3)))>, "ixd32">; - let isCommutable = 1 in + let isCommutable = 1, isAdd = 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", []>; - // TODO: incf32. + def INCF32 : I_5_ZX<0x3, 0x1, "incf32", uimm5, []>; + def INCT32 : I_5_ZX<0x3, 0x2, "inct32", uimm5, []>; + def DECF32 : I_5_ZX<0x3, 0x4, "decf32", uimm5, []>; + def DECT32 : I_5_ZX<0x3, 0x8, "dect32", uimm5, []>; + + def DIVS32 : R_YXZ_SP_F1<0x20, 0x2, BinOpFrag<(sdiv node:$LHS, node:$RHS)>, "divs32">; def DIVU32 : R_YXZ_SP_F1<0x20, 0x1, @@ -228,11 +258,13 @@ def DECNE32 : I_5_XZ<0x4, 0x4, "decne32", (outs GPR:$rz, CARRY:$cout), (ins GPR:$rx, uimm5:$imm5), []>; - // TODO: s/zext. - def ZEXT32 : I_5_XZ_U<0x15, (outs GPR:$rz), - (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "zext32",[]>; - def SEXT32 : I_5_XZ_U<0x16, (outs GPR:$rz), - (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "sext32", []>; + def SEXT32 : I_5_XZ_U<0x16, (outs GPR:$rz), (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "sext32", []>; + def SEXTB32 : I_5_XZ_US<0x16, 0, 7, "sextb32", sext_inreg, i8>; + def SEXTH32 : I_5_XZ_US<0x16, 0, 15, "sexth32", sext_inreg, i16>; + def ZEXTB32 : I_5_XZ_UZ<0x15, 0, 7, "zextb32", 255>; + def ZEXTH32 : I_5_XZ_UZ<0x15, 0, 15, "zexth32", 65535>; + def ZEXT32 : I_5_XZ_U<0x15, (outs GPR:$rz), (ins GPR:$rx, uimm5:$msb, uimm5:$lsb), "zext32",[]>; + //===----------------------------------------------------------------------===// // Load & Store instructions. @@ -246,7 +278,10 @@ def LD32BS : I_LD; def LD32HS : I_LD; - // TODO: LDM and STM. + def LDM32 : I_5_YX<0b110100, 0b000111, + (outs regseq:$regs), (ins GPR:$rx), "ldm32\t$regs, (${rx})", []>; + def STM32 : I_5_YX<0b110101, 0b000111, + (outs), (ins regseq:$regs, GPR:$rx), "stm32\t$regs, (${rx})", []>; def ST32B : I_ST; @@ -263,8 +298,6 @@ def STR32H : I_STR<0x1, "str32.h">; def STR32W : I_STR<0x2, "str32.w">; - //TODO: SPILL_CARRY and RESTORE_CARRY. - //===----------------------------------------------------------------------===// // Compare instructions. //===----------------------------------------------------------------------===// @@ -278,13 +311,35 @@ def CMPHS32 : R_YX<0x1, 0x1, "cmphs32">; def CMPLT32 : R_YX<0x1, 0x2, "cmplt32">; - // TODO: setc and clrc. - // TODO: test32 and tstnbz. + def SETC32 : CSKY32Inst { + let Inst{25 - 21} = 0; //rx + let Inst{20 - 16} = 0; //ry + let Inst{15 - 10} = 0x1; + let Inst{9 - 5} = 0x1; + let Inst{4 - 0} = 0; + let isCompare = 1; + } + def CLRC32 : CSKY32Inst { + let Inst{25 - 21} = 0; //rx + let Inst{20 - 16} = 0; //ry + let Inst{15 - 10} = 0x1; + let Inst{9 - 5} = 0x4; + let Inst{4 - 0} = 0; + let isCompare = 1; + } + + def TST32 : R_YX<0x8, 0x4, "tst32">; + def TSTNBZ32 : R_X<0x8, 0x8, + (outs CARRY:$ca), (ins GPR:$rx), "tstnbz32", []>; + //===----------------------------------------------------------------------===// // Data move instructions. //===----------------------------------------------------------------------===// + def MOVT32 : R_ZX<0x3, 0x2, "movt32", []>; def MOVF32 : R_ZX<0x3, 0x1, "movf32", []>; def MOVI32 : I_16_MOV<0x10, "movi32", uimm16>; @@ -292,13 +347,11 @@ def MVC32 : R_Z_1<0x1, 0x8, "mvc32">; def MOV32 : R_XZ<0x12, 0x1, "mov32">; - // TODO: ISEL Pseudo. - def MVCV32 : R_Z_1<0x1, 0x10, "mvcv32">; - // TODO: clrf and clrt. def CLRF32 : R_Z_2<0xB, 0x1, "clrf32", []>; def CLRT32 : R_Z_2<0xB, 0x2, "clrt32", []>; + //===----------------------------------------------------------------------===// // Branch and call instructions. //===----------------------------------------------------------------------===// @@ -314,7 +367,6 @@ "bf32\t$imm16", []>; } - def BEZ32 : I_16_X_L<0x8, "bez32", br_symbol>; def BNEZ32 : I_16_X_L<0x9, "bnez32", br_symbol>; def BHZ32 : I_16_X_L<0xA, "bhz32", br_symbol>; @@ -360,14 +412,73 @@ def GRS32 : I_18_Z_L<0x3, "grs32\t$rz, $offset", (outs GPR:$rz), (ins bare_symbol:$offset), []>; + let mayLoad = 1, mayStore = 0 in { def LRW32 : I_16_Z_L<0x14, "lrw32", (ins constpool_symbol:$imm16), []>; let isCodeGenOnly = 1 in -def LRW32_Gen : I_16_Z_L<0x14, "lrw32", - (ins bare_symbol:$src1, constpool_symbol:$imm16), []>; +def LRW32_Gen : I_16_Z_L<0x14, "lrw32", (ins bare_symbol:$src1, constpool_symbol:$imm16), []>; } -// TODO: Atomic and fence instructions. -// TODO: Other operations. +//===----------------------------------------------------------------------===// +// Atomic and fence instructions. +//===----------------------------------------------------------------------===// + + def BRWARW : BAR<0b01111, "bar.brwarw", 0>; + def BRWARWS : BAR<0b01111, "bar.brwarws", 1>; + def BRARW : BAR<0b00111, "bar.brarw", 0>; + def BRARWS : BAR<0b00111, "bar.brarws", 1>; + def BRWAW : BAR<0b01110, "bar.brwaw", 0>; + def BRWAWS : BAR<0b01110, "bar.brwaws", 1>; + def BRAR : BAR<0b00101, "bar.brar", 0>; + def BRARS : BAR<0b00101, "bar.brars", 1>; + def BWAW : BAR<0b01010, "bar.bwaw", 0>; + def BWAWS : BAR<0b01010, "bar.bwaws", 1>; + + def LDEX32W : I_LD; + let Constraints = "$rd = $rz" in + def STEX32W : I_LDST; + + +//===----------------------------------------------------------------------===// +// Other operation instructions. +//===----------------------------------------------------------------------===// + + def BREV32 : R_XZ<0x18, 0x10, "brev32">; + def ABS32 : R_XZ<0x0, 0x10, "abs32">; + def BGENR32 : R_XZ<0x14, 0x2, "bgenr32">; + + + def REVB32 : R_XZ<0x18, 0x4, "revb32">; + def REVH32 : R_XZ<0x18, 0x8, "revh32">; + def FF0 : R_XZ<0x1F, 0x1, "ff0.32">; + def FF1 : R_XZ<0x1F, 0x2, "ff1.32">; + def XTRB0 : R_XZ<0x1C, 0x1, "xtrb0.32">; + def XTRB1 : R_XZ<0x1C, 0x2, "xtrb1.32">; + def XTRB2 : R_XZ<0x1C, 0x4, "xtrb2.32">; + def XTRB3 : R_XZ<0x1C, 0x8, "xtrb3.32">; + def BTSTI32 : I_5_X<0x0A, 0x4, "btsti32", uimm5, []>; + def BCLRI32 : I_5_XZ<0xA, 0x1, "bclri32", + (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5), []>; + def BSETI32 : I_5_XZ<0xA, 0x2, "bseti32", + (outs GPR:$rz), (ins GPR:$rx, uimm5:$imm5), []>; + + +//===----------------------------------------------------------------------===// +// Special instructions. +//===----------------------------------------------------------------------===// + +def SYNC32 : I_5_XZ_SYNC<1, 1, "sync32", 0, 0>; +def SYNC32S : I_5_XZ_SYNC<1, 1, "sync32.s", 1, 0>; +def SYNC32I : I_5_XZ_SYNC<1, 1, "sync32.i", 0, 1>; +def SYNC32IS : I_5_XZ_SYNC<1, 1, "sync32.is", 1, 1>; + + + def RFI32 : I_5_XZ_PRIVI<0x11, 0x1, "rfi32">; + +def STOP32 : I_5_XZ_PRIVI<0x12, 0x1, "stop32">; +def WAIT32 : I_5_XZ_PRIVI<0x13, 0x1, "wait32">; +def DOZE32 : I_5_XZ_PRIVI<0x14, 0x1, "doze32">; + // TODO: Special instructions. -// TODO: Pseudo for assembly. +// TODO: Pseudo for assembly. \ No newline at end of file Index: llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h =================================================================== --- llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h +++ llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.h @@ -42,6 +42,8 @@ void printCustomAliasOperand(const MCInst *MI, uint64_t Address, unsigned OpIdx, unsigned PrintMethodIdx, const MCSubtargetInfo &STI, raw_ostream &O); + void printRegSeq(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, + raw_ostream &O); static const char *getRegisterName(unsigned RegNo); static const char *getRegisterName(unsigned RegNo, unsigned AltIdx); Index: llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp =================================================================== --- llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp +++ llvm/lib/Target/CSKY/MCTargetDesc/CSKYInstPrinter.cpp @@ -95,6 +95,16 @@ MO.getExpr()->print(O, &MAI); } +void CSKYInstPrinter::printRegSeq(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O) { + auto Ry = MI->getOperand(OpNo).getReg(); + auto Rz = MI->getOperand(OpNo + 1).getImm(); + + printRegName(O, Ry); + O << "-"; + printRegName(O, Rz); +} + const char *CSKYInstPrinter::getRegisterName(unsigned RegNo) { return getRegisterName(RegNo, ArchRegNames ? CSKY::NoRegAltName : CSKY::ABIRegAltName); Index: llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h =================================================================== --- llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h +++ llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h @@ -53,6 +53,10 @@ return (MO.getImm() >> shift); } + unsigned getRegSeqImmOpValue(const MCInst &MI, unsigned Idx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getOImmOpValue(const MCInst &MI, unsigned Idx, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; Index: llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp =================================================================== --- llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp +++ llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.cpp @@ -31,6 +31,22 @@ return MO.getImm() - 1; } +unsigned +CSKYMCCodeEmitter::getRegSeqImmOpValue(const MCInst &MI, unsigned Idx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + assert(MI.getOperand(Idx).isReg() && "Unexpected MO type."); + assert(MI.getOperand(Idx + 1).isImm() && "Unexpected MO type."); + + unsigned Ry = MI.getOperand(Idx).getReg(); + unsigned Rz = MI.getOperand(Idx + 1).getImm(); + + unsigned Imm = Ctx.getRegisterInfo()->getEncodingValue(Rz) - + Ctx.getRegisterInfo()->getEncodingValue(Ry); + + return ((Ctx.getRegisterInfo()->getEncodingValue(Ry) << 5) | Imm); +} + void CSKYMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { Index: llvm/test/MC/CSKY/basic.s =================================================================== --- llvm/test/MC/CSKY/basic.s +++ llvm/test/MC/CSKY/basic.s @@ -1,4 +1,4 @@ -# RUN: llvm-mc %s -triple=csky -show-encoding | FileCheck -check-prefixes=CHECK-ASM %s +# RUN: llvm-mc %s -triple=csky -show-encoding -csky-no-aliases | FileCheck -check-prefixes=CHECK-ASM %s # CHECK-ASM: addi32 a0, sp, 2 # CHECK-ASM: encoding: [0x0e,0xe4,0x01,0x00] @@ -40,6 +40,46 @@ # CHECK-ASM: encoding: [0x4e,0xc4,0x00,0x49] rotli32 a0, sp, 2 +# CHECK-ASM: incf32 a0, sp, 2 +# CHECK-ASM: encoding: [0x0e,0xc4,0x22,0x0c] +incf32 a0, sp, 2 + +# CHECK-ASM: inct32 a0, sp, 2 +# CHECK-ASM: encoding: [0x0e,0xc4,0x42,0x0c] +inct32 a0, sp, 2 + +# CHECK-ASM: decf32 a0, sp, 2 +# CHECK-ASM: encoding: [0x0e,0xc4,0x82,0x0c] +decf32 a0, sp, 2 + +# CHECK-ASM: dect32 a0, sp, 2 +# CHECK-ASM: encoding: [0x0e,0xc4,0x02,0x0d] +dect32 a0, sp, 2 + +# CHECK-ASM: decgt32 a0, sp, 2 +# CHECK-ASM: encoding: [0x4e,0xc4,0x20,0x10] +decgt32 a0, sp, 2 + +# CHECK-ASM: declt32 a0, sp, 2 +# CHECK-ASM: encoding: [0x4e,0xc4,0x40,0x10] +declt32 a0, sp, 2 + +# CHECK-ASM: decne32 a0, sp, 2 +# CHECK-ASM: encoding: [0x4e,0xc4,0x80,0x10] +decne32 a0, sp, 2 + +# CHECK-ASM: btsti32 a0, 2 +# CHECK-ASM: encoding: [0x40,0xc4,0x80,0x28] +btsti32 a0, 2 + +# CHECK-ASM: bclri32 a0, sp, 2 +# CHECK-ASM: encoding: [0x4e,0xc4,0x20,0x28] +bclri32 a0, sp, 2 + +# CHECK-ASM: bseti32 a0, sp, 2 +# CHECK-ASM: encoding: [0x4e,0xc4,0x40,0x28] +bseti32 a0, sp, 2 + # CHECK-ASM: cmpnei32 a0, 2 # CHECK-ASM: encoding: [0x40,0xeb,0x02,0x00] cmpnei32 a0, 2 @@ -92,6 +132,10 @@ # CHECK-ASM: encoding: [0xa4,0xc4,0x23,0x40] lsl32 a3, l0, l1 +# CHECK-ASM: rotl32 a3, l0, l1 +# CHECK-ASM: encoding: [0xa4,0xc4,0x03,0x41] +rotl32 a3, l0, l1 + # CHECK-ASM: lsr32 a3, l0, l1 # CHECK-ASM: encoding: [0xa4,0xc4,0x43,0x40] lsr32 a3, l0, l1 @@ -100,6 +144,22 @@ # CHECK-ASM: encoding: [0xa4,0xc4,0x83,0x40] asr32 a3, l0, l1 +# CHECK-ASM: lslc32 a0, sp, 2 +# CHECK-ASM: encoding: [0x2e,0xc4,0x20,0x4c] +lslc32 a0, sp, 2 + +# CHECK-ASM: lsrc32 a0, sp, 2 +# CHECK-ASM: encoding: [0x2e,0xc4,0x40,0x4c] +lsrc32 a0, sp, 2 + +# CHECK-ASM: asrc32 a0, sp, 2 +# CHECK-ASM: encoding: [0x2e,0xc4,0x80,0x4c] +asrc32 a0, sp, 2 + +# CHECK-ASM: xsr32 a0, sp, 2 +# CHECK-ASM: encoding: [0x2e,0xc4,0x00,0x4d] +xsr32 a0, sp, 2 + # CHECK-ASM: mult32 a3, l0, l1 # CHECK-ASM: encoding: [0xa4,0xc4,0x23,0x84] mult32 a3, l0, l1 @@ -152,6 +212,10 @@ # CHECK-ASM: encoding: [0x0e,0xd8,0x01,0x20] ld32.w a0, (sp, 4) +# CHECK-ASM: ldex32.w a0, (sp, 4) +# CHECK-ASM: encoding: [0x0e,0xd8,0x01,0x70] +ldex32.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) @@ -184,6 +248,10 @@ # CHECK-ASM: encoding: [0x0e,0xdc,0x01,0x20] st32.w a0, (sp, 4) +# CHECK-ASM: stex32.w a0, (sp, 4) +# CHECK-ASM: encoding: [0x0e,0xdc,0x01,0x70] +stex32.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) @@ -212,6 +280,50 @@ # CHECK-ASM: encoding: [0x64,0xc4,0x20,0x0c] movf32 a3, l0 +# CHECK-ASM: brev32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0x03,0x62] +brev32 a3, l0 + +# CHECK-ASM: abs32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0x03,0x02] +abs32 a3, l0 + +# CHECK-ASM: bgenr32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0x43,0x50] +bgenr32 a3, l0 + +# CHECK-ASM: revb32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0x83,0x60] +revb32 a3, l0 + +# CHECK-ASM: revh32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0x03,0x61] +revh32 a3, l0 + +# CHECK-ASM: ff0.32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0x23,0x7c] +ff0.32 a3, l0 + +# CHECK-ASM: ff1.32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0x43,0x7c] +ff1.32 a3, l0 + +# CHECK-ASM: xtrb0.32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0x23,0x70] +xtrb0.32 a3, l0 + +# CHECK-ASM: xtrb1.32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0x43,0x70] +xtrb1.32 a3, l0 + +# CHECK-ASM: xtrb2.32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0x83,0x70] +xtrb2.32 a3, l0 + +# CHECK-ASM: xtrb3.32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0x03,0x71] +xtrb3.32 a3, l0 + # CHECK-ASM: mvc32 a3 # CHECK-ASM: encoding: [0x00,0xc4,0x03,0x05] mvc32 a3 @@ -236,10 +348,130 @@ # CHECK-ASM: encoding: [0x04,0xc4,0xe3,0x54] zext32 a3, l0, 7, 0 +# CHECK-ASM: zextb32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0xe3,0x54] +zextb32 a3, l0 + +# CHECK-ASM: zexth32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0xe3,0x55] +zexth32 a3, l0 + # CHECK-ASM: sext32 a3, l0, 7, 0 # CHECK-ASM: encoding: [0x04,0xc4,0xe3,0x58] sext32 a3, l0, 7, 0 +# CHECK-ASM: sextb32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0xe3,0x58] +sextb32 a3, l0 + +# CHECK-ASM: sexth32 a3, l0 +# CHECK-ASM: encoding: [0x04,0xc4,0xe3,0x59] +sexth32 a3, l0 + +# CHECK-ASM: ldm32 l1-l3, (a0) +# CHECK-ASM: encoding: [0xa0,0xd0,0x22,0x1c] +ldm32 r5-r7, (a0) + +# CHECK-ASM: stm32 l1-l3, (a0) +# CHECK-ASM: encoding: [0xa0,0xd4,0x22,0x1c] +stm32 r5-r7, (a0) + +# CHECK-ASM: setc32 +# CHECK-ASM: encoding: [0x00,0xc4,0x20,0x04] +setc32 + +# CHECK-ASM: clrc32 +# CHECK-ASM: encoding: [0x00,0xc4,0x80,0x04] +clrc32 + +# CHECK-ASM: tst32 a3, l0 +# CHECK-ASM: encoding: [0x83,0xc4,0x80,0x20] +tst32 a3, l0 + +# CHECK-ASM: tstnbz32 a3 +# CHECK-ASM: encoding: [0x03,0xc4,0x00,0x21] +tstnbz32 a3 + +# CHECK-ASM: clrf32 a3 +# CHECK-ASM: encoding: [0x60,0xc4,0x20,0x2c] +clrf32 a3 + +# CHECK-ASM: clrt32 a3 +# CHECK-ASM: encoding: [0x60,0xc4,0x40,0x2c] +clrt32 a3 + +# CHECK-ASM: bar.brwarw +# CHECK-ASM: encoding: [0x00,0xc0,0x2f,0x84] +bar.brwarw + +# CHECK-ASM: bar.brwarws +# CHECK-ASM: encoding: [0x00,0xc2,0x2f,0x84] +bar.brwarws + +# CHECK-ASM: bar.brarw +# CHECK-ASM: encoding: [0x00,0xc0,0x27,0x84] +bar.brarw + +# CHECK-ASM: bar.brarws +# CHECK-ASM: encoding: [0x00,0xc2,0x27,0x84] +bar.brarws + +# CHECK-ASM: bar.brwaw +# CHECK-ASM: encoding: [0x00,0xc0,0x2e,0x84] +bar.brwaw + +# CHECK-ASM: bar.brwaws +# CHECK-ASM: encoding: [0x00,0xc2,0x2e,0x84] +bar.brwaws + +# CHECK-ASM: bar.brar +# CHECK-ASM: encoding: [0x00,0xc0,0x25,0x84] +bar.brar + +# CHECK-ASM: bar.brars +# CHECK-ASM: encoding: [0x00,0xc2,0x25,0x84] +bar.brars + +# CHECK-ASM: bar.bwaw +# CHECK-ASM: encoding: [0x00,0xc0,0x2a,0x84] +bar.bwaw + +# CHECK-ASM: bar.bwaws +# CHECK-ASM: encoding: [0x00,0xc2,0x2a,0x84] +bar.bwaws + +# CHECK-ASM: sync32 +# CHECK-ASM: encoding: [0x00,0xc0,0x20,0x04] +sync32 + +# CHECK-ASM: sync32.s +# CHECK-ASM: encoding: [0x00,0xc2,0x20,0x04] +sync32.s + +# CHECK-ASM: sync32.i +# CHECK-ASM: encoding: [0x20,0xc0,0x20,0x04] +sync32.i + +# CHECK-ASM: sync32.is +# CHECK-ASM: encoding: [0x20,0xc2,0x20,0x04] +sync32.is + +# CHECK-ASM: rfi32 +# CHECK-ASM: encoding: [0x00,0xc0,0x20,0x44] +rfi32 + +# CHECK-ASM: stop32 +# CHECK-ASM: encoding: [0x00,0xc0,0x20,0x48] +stop32 + +# CHECK-ASM: wait32 +# CHECK-ASM: encoding: [0x00,0xc0,0x20,0x4c] +wait32 + +# CHECK-ASM: doze32 +# CHECK-ASM: encoding: [0x00,0xc0,0x20,0x50] +doze32 + # CHECK-ASM: br32 .L.test # CHECK-ASM: encoding: [A,0xe8'A',A,A] # CHECK-ASM: fixup A - offset: 0, value: .L.test, kind: fixup_csky_pcrel_imm16_scale2 @@ -324,6 +556,10 @@ # CHECK-ASM: encoding: [0xcf,0xe8,0x00,0x00] rts32 +# CHECK-ASM: rte32 +# CHECK-ASM: encoding: [0x00,0xc0,0x20,0x40] +rte32 + # CHECK-ASM: grs32 a0, .L.test13 # CHECK-ASM: encoding: [0x0c'A',0xcc'A',A,A] # CHECK-ASM: fixup A - offset: 0, value: .L.test13, kind: fixup_csky_pcrel_imm18_scale2 @@ -347,12 +583,27 @@ andni32 a0, a0, 4096 # CHECK: :[[#@LINE]]:17: error: immediate must be an integer in the range [0, 4095] xori32 a0, a0, 4096 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [0, 4095] +# oimm5 +lslc32 a0, a0, 33 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [1, 32] +lsrc32 a0, a0, 33 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [1, 32] +asrc32 a0, a0, 33 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [1, 32] +xsr32 a0, a0, 33 # CHECK: :[[#@LINE]]:15: error: immediate must be an integer in the range [1, 32] # uimm5 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] +incf32 a0, a0, 32 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [0, 31] +inct32 a0, a0, 32 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [0, 31] +decf32 a0, a0, 32 # CHECK: :[[#@LINE]]:16: error: immediate must be an integer in the range [0, 31] +dect32 a0, a0, 32 # CHECK: :[[@LINE]]:16: error: immediate must be an integer in the range [0, 31] +decgt32 a0, a0, 32 # CHECK: :[[#@LINE]]:17: error: immediate must be an integer in the range [0, 31] +declt32 a0, a0, 32 # CHECK: :[[#@LINE]]:17: error: immediate must be an integer in the range [0, 31] +decne32 a0, a0, 32 # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 31] +btsti32 a0, 32 # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [0, 31] +bclri32 a0, a0, 32 # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 31] +bseti32 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] @@ -360,6 +611,8 @@ 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] +ldex32.w a0, (a0, 2) # CHECK: :[[@LINE]]:19: 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] @@ -371,6 +624,7 @@ 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] +stex32.w a0, (a0, 2) # CHECK: :[[@LINE]]:19: 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] @@ -409,4 +663,8 @@ jmpi32 0x100 # CHECK: :[[@LINE]]:8: error: operand must be a constpool symbol name bsr32 0x100 # CHECK: :[[@LINE]]:7: error: operand must be a symbol name +# Reg Sequence +ldm32 r2-r0, (a0) # CHECK: :[[@LINE]]:7: error: operand must be a register sequence like (rN-rM, N<=M) +ldm32 r0-r34, (a0) # CHECK: :[[@LINE]]:10: error: invalid register + .endif