Skip to content

Commit

Permalink
[CSKY 5/n] Add support for all CSKY basic integer instructions except…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
zixuan-wu committed Apr 20, 2021
1 parent 8ba622b commit 4216389
Show file tree
Hide file tree
Showing 5 changed files with 407 additions and 46 deletions.
92 changes: 86 additions & 6 deletions llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -132,13 +133,13 @@ struct CSKYOperand : public MCParsedAsmOperand {
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 {
Expand All @@ -150,18 +151,25 @@ struct CSKYOperand : public MCParsedAsmOperand {
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; }
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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!");
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down
59 changes: 25 additions & 34 deletions llvm/lib/Target/CSKY/CSKYInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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]>
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 4216389

Please sign in to comment.