Skip to content

Commit

Permalink
[CSKY 6/n] Add support branch and symbol series instruction
Browse files Browse the repository at this point in the history
This patch adds basic CSKY branch instructions and symbol address series instructions.
Those two kinds of instruction have relationship between each other, and it involves much work about Fixups.

For now, basic instructions are enabled except for disassembler support.
We would support to generate basic codegen asm firstly and delay disassembler work later.

Differential Revision: https://reviews.llvm.org/D95029
  • Loading branch information
zixuan-wu committed Apr 20, 2021
1 parent 4216389 commit 4bb60c2
Show file tree
Hide file tree
Showing 13 changed files with 817 additions and 11 deletions.
96 changes: 96 additions & 0 deletions llvm/lib/Target/CSKY/AsmParser/CSKYAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/CSKYMCExpr.h"
#include "MCTargetDesc/CSKYMCTargetDesc.h"
#include "TargetInfo/CSKYTargetInfo.h"
#include "llvm/ADT/STLExtras.h"
Expand Down Expand Up @@ -58,6 +59,8 @@ class CSKYAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseImmediate(OperandVector &Operands);
OperandMatchResultTy parseRegister(OperandVector &Operands);
OperandMatchResultTy parseBaseRegImm(OperandVector &Operands);
OperandMatchResultTy parseCSKYSymbol(OperandVector &Operands);
OperandMatchResultTy parseConstpoolSymbol(OperandVector &Operands);

bool parseOperand(OperandVector &Operands, StringRef Mnemonic);

Expand Down Expand Up @@ -171,6 +174,20 @@ struct CSKYOperand : public MCParsedAsmOperand {
bool isUImm12Shift1() { return isUImm<12, 1>(); }
bool isUImm12Shift2() { return isUImm<12, 2>(); }

bool isSImm16Shift1() { return isSImm<16, 1>(); }

bool isCSKYSymbol() const {
int64_t Imm;
// Must be of 'immediate' type but not a constant.
return isImm() && !evaluateConstantImm(getImm(), Imm);
}

bool isConstpoolSymbol() const {
int64_t Imm;
// Must be of 'immediate' type but not a constant.
return isImm() && !evaluateConstantImm(getImm(), Imm);
}

/// Gets location of the first token of this operand.
SMLoc getStartLoc() const override { return StartLoc; }
/// Gets location of the last token of this operand.
Expand Down Expand Up @@ -350,6 +367,14 @@ bool CSKYAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
"immediate must be a multiple of 4 bytes in the range");
case Match_InvalidUImm16:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 16) - 1);
case Match_InvalidCSKYSymbol: {
SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "operand must be a symbol name");
}
case Match_InvalidConstpool: {
SMLoc ErrorLoc = ((CSKYOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "operand must be a constpool symbol name");
}
}

llvm_unreachable("Unknown match type detected!");
Expand Down Expand Up @@ -482,6 +507,15 @@ OperandMatchResultTy CSKYAsmParser::parseImmediate(OperandVector &Operands) {
/// information, adding to Operands. If operand was parsed, returns false, else
/// true.
bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
// Check if the current operand has a custom associated parser, if so, try to
// custom parse the operand, or fallback to the general approach.
OperandMatchResultTy Result =
MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
if (Result == MatchOperand_Success)
return false;
if (Result == MatchOperand_ParseFail)
return true;

// Attempt to parse token as register
if (parseRegister(Operands) == MatchOperand_Success)
return false;
Expand All @@ -500,6 +534,68 @@ bool CSKYAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
return true;
}

OperandMatchResultTy CSKYAsmParser::parseCSKYSymbol(OperandVector &Operands) {
SMLoc S = getLoc();
SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);

if (getLexer().getKind() != AsmToken::Identifier)
return MatchOperand_NoMatch;

StringRef Identifier;
if (getParser().parseIdentifier(Identifier))
return MatchOperand_ParseFail;

CSKYMCExpr::VariantKind Kind = CSKYMCExpr::VK_CSKY_None;

if (Identifier.consume_back("@GOT"))
Kind = CSKYMCExpr::VK_CSKY_GOT;
else if (Identifier.consume_back("@GOTOFF"))
Kind = CSKYMCExpr::VK_CSKY_GOTOFF;
else if (Identifier.consume_back("@PLT"))
Kind = CSKYMCExpr::VK_CSKY_PLT;
else if (Identifier.consume_back("@GOTPC"))
Kind = CSKYMCExpr::VK_CSKY_GOTPC;

MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
const MCExpr *Res =
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());

if (Kind != CSKYMCExpr::VK_CSKY_None)
Res = CSKYMCExpr::create(Res, Kind, getContext());

Operands.push_back(CSKYOperand::createImm(Res, S, E));
return MatchOperand_Success;
}

OperandMatchResultTy
CSKYAsmParser::parseConstpoolSymbol(OperandVector &Operands) {
SMLoc S = getLoc();
SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);

if (getLexer().getKind() != AsmToken::LBrac)
return MatchOperand_NoMatch;

getLexer().Lex(); // Eat '['.

if (getLexer().getKind() != AsmToken::Identifier)
return MatchOperand_NoMatch;

StringRef Identifier;
if (getParser().parseIdentifier(Identifier))
return MatchOperand_ParseFail;

if (getLexer().getKind() != AsmToken::RBrac)
return MatchOperand_NoMatch;

getLexer().Lex(); // Eat ']'.

MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
const MCExpr *Res =
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Operands.push_back(CSKYOperand::createImm(Res, S, E));
return MatchOperand_Success;
}

bool CSKYAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) {
// First operand is token for instruction.
Expand Down
27 changes: 20 additions & 7 deletions llvm/lib/Target/CSKY/CSKYInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@ class J<bits<6> opcode, dag outs, dag ins, string op, list<dag> pattern>
pattern> {
bits<26> offset;
let Inst{25 - 0} = offset;
let isCall = 1;
let Defs = [ R15 ];
}

// 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, dag outs, dag ins, list<dag> pattern>
: CSKY32Inst<AddrModeNone, 0x33, outs, ins,
!strconcat(op, "\t$rz, $offset"), pattern> {
class I_18_Z_L<bits<3> sop, string asm, dag outs, dag ins, list<dag> pattern>
: CSKY32Inst<AddrModeNone, 0x33, outs, ins, asm, pattern> {
bits<5> rz;
bits<18> offset;
let Inst{25 - 21} = rz;
Expand Down Expand Up @@ -102,7 +103,7 @@ class I_16_MOV<bits<5> sop, string op, ImmLeaf ImmType>
// Instructions(1): lrw32
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> {
!strconcat(op, "\t$rz, $imm16"), pattern> {
bits<5> rz;
bits<16> imm16;
let Inst{25 - 21} = sop;
Expand All @@ -112,9 +113,8 @@ class I_16_Z_L<bits<5> sop, string op, dag ins, list<dag> pattern>

// Format< OP[6] | SOP[5] | 00000[5] | OFFSET[16] >
// Instructions(5): bt32, bf32, br32, jmpi32, jsri32
class I_16_L<bits<5> sop, dag outs, dag ins, string op, list<dag> pattern>
: CSKY32Inst<AddrModeNone, 0x3a, outs, ins, !strconcat(op, "\t$imm16"),
pattern> {
class I_16_L<bits<5> sop, dag outs, dag ins, string asm, list<dag> pattern>
: CSKY32Inst<AddrModeNone, 0x3a, outs, ins, asm, pattern> {
bits<16> imm16;
let Inst{25 - 21} = sop;
let Inst{20 - 16} = 0;
Expand Down Expand Up @@ -159,6 +159,19 @@ class I_16_RET<bits<5> sop, bits<5> pcode, string op, list<dag> pattern>
let isBarrier = 1;
}

// Instructions(1): rte32
class I_16_RET_I<bits<5> sop, bits<5> pcode, string op, list<dag> pattern>
: CSKY32Inst<AddrModeNone, 0x30, (outs), (ins), op, pattern> {
let Inst{25 - 21} = sop;
let Inst{20 - 16} = pcode;
let Inst{15 - 10} = 0x10;
let Inst{9 - 5} = 1;
let Inst{4 - 0} = 0;
let isTerminator = 1;
let isReturn = 1;
let isBarrier = 1;
}

// Format< OP[6] | SOP[5] | RX[5] | IMM16[16] >
// Instructions(3): cmpnei32, cmphsi32, cmplti32
class I_16_X<bits<5> sop, string op, Operand operand>
Expand Down
105 changes: 104 additions & 1 deletion llvm/lib/Target/CSKY/CSKYInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
// CSKY specific DAG Nodes.
//===----------------------------------------------------------------------===//

// TODO: Add CSKY specific DAG Nodes.
// Target-dependent nodes.
def CSKY_RET : SDNode<"CSKYISD::RET", SDTNone,
[SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;

//===----------------------------------------------------------------------===//
// Operand and SDNode transformation definitions.
Expand Down Expand Up @@ -81,6 +83,41 @@ def uimm_shift : Operand<i32>, ImmLeaf<i32, "return isUInt<2>(Imm);"> {
let ParserMatchClass = UImmAsmOperand<2>;
}

def CSKYSymbol : AsmOperandClass {
let Name = "CSKYSymbol";
let RenderMethod = "addImmOperands";
let DiagnosticType = "InvalidCSKYSymbol";
let ParserMethod = "parseCSKYSymbol";
}

def br_symbol : Operand<iPTR> {
let EncoderMethod =
"getBranchSymbolOpValue<CSKY::fixup_csky_pcrel_imm16_scale2>";
let ParserMatchClass = CSKYSymbol;
}

def call_symbol : Operand<iPTR> {
let ParserMatchClass = CSKYSymbol;
let EncoderMethod = "getCallSymbolOpValue";
}

def Constpool : AsmOperandClass {
let Name = "ConstpoolSymbol";
let RenderMethod = "addImmOperands";
let DiagnosticType = "InvalidConstpool";
let ParserMethod = "parseConstpoolSymbol";
}

def constpool_symbol : Operand<iPTR> {
let ParserMatchClass = Constpool;
let EncoderMethod =
"getConstpoolSymbolOpValue<CSKY::fixup_csky_pcrel_uimm16_scale4>";
}

def bare_symbol : Operand<iPTR> {
let ParserMatchClass = CSKYSymbol;
let EncoderMethod = "getBareSymbolOpValue";
}

def oimm12 : oimm<12>;
def oimm16 : oimm<16>;
Expand Down Expand Up @@ -229,3 +266,69 @@ 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">;

//===----------------------------------------------------------------------===//
// Branch and call instructions.
//===----------------------------------------------------------------------===//

let isBranch = 1, isTerminator = 1 in {
let isBarrier = 1, isPredicable = 1 in
def BR32 : I_16_L<0x0, (outs), (ins br_symbol:$imm16), "br32\t$imm16",
[(br bb:$imm16)]>;

def BT32 : I_16_L<0x3, (outs), (ins CARRY:$ca, br_symbol:$imm16),
"bt32\t$imm16", [(brcond CARRY:$ca, bb:$imm16)]>;
def BF32 : I_16_L<0x2, (outs), (ins CARRY:$ca, br_symbol:$imm16),
"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>;
def BLSZ32 : I_16_X_L<0xB, "blsz32", br_symbol>;
def BLZ32 : I_16_X_L<0xC, "blz32", br_symbol>;
def BHSZ32 : I_16_X_L<0xD, "bhsz32", br_symbol>;

let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
def JMP32 : I_16_JX<0x6, "jmp32", [(brind GPR:$rx)]>; // jmp to register
def JMPI32 : I_16_L<0x16, (outs), (ins constpool_symbol:$imm16),
"jmpi32\t$imm16", []>;
}

let isCall = 1, Defs = [ R15 ] in
def JSR32 : I_16_JX<0x7, "jsr32", []>;

let isCall = 1, Defs = [ R15 ] , mayLoad = 1 in
def JSRI32: I_16_L<0x17, (outs),
(ins constpool_symbol:$imm16), "jsri32\t$imm16", []>;


def BSR32 : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>;

def BSR32_BR : J<0x38, (outs), (ins call_symbol:$offset), "bsr32", []>{
let isCodeGenOnly = 1;
let isBranch = 1;
let isTerminator = 1;
let isBarrier = 1;
let isPredicable = 1;
let Defs = [ R15 ];
}

def RTS32 : I_16_RET<0x6, 0xF, "rts32", [(CSKY_RET)]>;


def RTE32 : I_16_RET_I<0, 0, "rte32", []>;

//===----------------------------------------------------------------------===//
// Symbol address instructions.
//===----------------------------------------------------------------------===//

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), []>;
}
1 change: 1 addition & 0 deletions llvm/lib/Target/CSKY/MCTargetDesc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_llvm_component_library(LLVMCSKYDesc
CSKYELFObjectWriter.cpp
CSKYInstPrinter.cpp
CSKYMCAsmInfo.cpp
CSKYMCExpr.cpp
CSKYMCTargetDesc.cpp
CSKYMCCodeEmitter.cpp

Expand Down
Loading

0 comments on commit 4bb60c2

Please sign in to comment.