diff --git a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp --- a/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp +++ b/llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp @@ -57,6 +57,7 @@ OperandMatchResultTy parseImmediate(OperandVector &Operands); OperandMatchResultTy parseRegister(OperandVector &Operands); + OperandMatchResultTy parseBaseRegImm(OperandVector &Operands); bool parseOperand(OperandVector &Operands, StringRef Mnemonic); @@ -132,13 +133,13 @@ return false; } - template bool isUImm() const { + template bool isUImm() const { if (!isImm()) return false; int64_t Imm; bool IsConstantImm = evaluateConstantImm(getImm(), Imm); - return IsConstantImm && isUInt(Imm); + return IsConstantImm && isShiftedUInt(Imm); } template bool isOImm() const { @@ -150,18 +151,25 @@ return IsConstantImm && isUInt(Imm - 1); } - template bool isSImm() const { + template bool isSImm() const { if (!isImm()) return false; int64_t Imm; bool IsConstantImm = evaluateConstantImm(getImm(), Imm); - return IsConstantImm && isInt(Imm); + return IsConstantImm && isShiftedInt(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 @@ 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 @@ 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::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 @@ 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 --- a/llvm/lib/Target/CSKY/CSKYInstrFormats.td +++ b/llvm/lib/Target/CSKY/CSKYInstrFormats.td @@ -58,8 +58,8 @@ // 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 sop, string op, Operand operand, list pattern> - : CSKY32Inst sop, string op, dag outs, dag ins, list pattern> + : CSKY32Inst { bits<5> rz; bits<18> offset; @@ -100,10 +100,9 @@ // Format< OP[6] | SOP[5] | RZ[5] | OFFSET[16] > // Instructions(1): lrw32 -class I_16_Z_L sop, string op, Operand operand, list pattern> - : CSKY32Inst { +class I_16_Z_L sop, string op, dag ins, list pattern> + : CSKY32Inst { bits<5> rz; bits<16> imm16; let Inst{25 - 21} = sop; @@ -122,13 +121,6 @@ let Inst{15 - 0} = imm16; } -// bt32, bf32, br32, jmpi32 -class I_16_L_B sop, string op, Operand operand, list pattern> - : I_16_L { - let isBranch = 1; - let isTerminator = 1; -} - // Format< OP[6] | SOP[5] | RX[5] | 0000000000000000[16] > // Instructions(2): jmp32, jsr32 class I_16_JX sop, string op, list pattern> @@ -169,9 +161,9 @@ // Format< OP[6] | SOP[5] | RX[5] | IMM16[16] > // Instructions(3): cmpnei32, cmphsi32, cmplti32 -class I_16_X sop, string op> +class I_16_X sop, string op, Operand operand> : CSKY32Inst { + (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_LDST opcode, bits<4> sop, dag outs, dag ins, string op, list pattern> - : CSKY32Inst { bits<5> rx; bits<5> rz; @@ -298,13 +290,13 @@ // 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 sop, bits<5> lsb, bits<5> msb, dag outs, dag ins, - string op, list pattern> - : CSKY32Inst(msb) #", " #!cast(lsb), +class I_5_XZ_U sop, dag outs, dag ins, string op, list pattern> + : CSKY32Inst { 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 @@ } // sextb, sexth -class I_5_XZ_US sop, bits<5> lsb, bits<5> msb, string op, SDNode opnode, - ValueType type> : I_5_XZ_U; +class I_5_XZ_US sop, string op, SDNode opnode, + ValueType type> : I_5_XZ_U; -class I_5_XZ_UZ sop, bits<5> lsb, bits<5> msb, string op, int v> - : I_5_XZ_U sop, string op, int v> + : I_5_XZ_U; // Format< OP[6] | RZ[5] | RX[5] | SOP[6] | SIZE[5] | LSB[5]> @@ -401,27 +393,26 @@ // 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 opcode, bits<6> sop, bits<5> pcode, int no, dag outs, +class R_YXZ_LDST opcode, bits<6> sop, dag outs, dag ins, string op, list pattern> : CSKY32Inst { + 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 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 sop, string op> : R_YXZ_LDST<0x34, sop, + (outs GPR:$rz), (ins GPR:$rx, GPR:$ry, uimm_shift:$imm), op, []>; -class I_STR 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 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 --- 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 uimm : Operand, ImmLeaf(Imm);"> { let EncoderMethod = "getImmOpValue<"#shift#">"; - let ParserMatchClass = UImmAsmOperand; + let ParserMatchClass = + !if(!ne(shift, 0), + UImmAsmOperand, + UImmAsmOperand); } class simm : Operand, @@ -65,13 +67,38 @@ let ParserMatchClass = UImmAsmOperand; } +def uimm32_hi16 : SDNodeXFormgetTargetConstant((N->getZExtValue() >> 16) & 0xFFFF, + SDLoc(N), MVT::i32); +}]>; +def uimm16_16_xform : Operand, + ImmLeaf(Imm);", uimm32_hi16> { + let ParserMatchClass = UImmAsmOperand<16>; +} + +def uimm_shift : Operand, ImmLeaf(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 BinOpFrag : PatFrag<(ops node:$LHS, node:$RHS), res>; class UnOpFrag : 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 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 @@ 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; +def LD32H : I_LD; +def LD32W : I_LD; +def LD32BS : I_LD; +def LD32HS : I_LD; + +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; +def ST32H : I_ST; +def ST32W : I_ST; + +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 --- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h +++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYMCCodeEmitter.h @@ -54,6 +54,14 @@ unsigned getOImmOpValue(const MCInst &MI, unsigned Idx, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + + unsigned getImmShiftOpValue(const MCInst &MI, unsigned Idx, + SmallVectorImpl &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 --- a/llvm/test/MC/CSKY/basic.s +++ b/llvm/test/MC/CSKY/basic.s @@ -32,6 +32,33 @@ # 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 @@ # 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 @@ 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 @@ 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