summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp156
-rw-r--r--llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp14
-rw-r--r--llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.h1
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h54
-rw-r--r--llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp19
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfo.td148
6 files changed, 378 insertions, 14 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index cb820379bbb..4b1eec9ec86 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "MCTargetDesc/RISCVBaseInfo.h"
#include "MCTargetDesc/RISCVMCTargetDesc.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
@@ -30,6 +31,9 @@ struct RISCVOperand;
class RISCVAsmParser : public MCTargetAsmParser {
SMLoc getLoc() const { return getParser().getTok().getLoc(); }
+ bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
+ int Lower, int Upper, Twine Msg);
+
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands, MCStreamer &Out,
uint64_t &ErrorInfo,
@@ -48,6 +52,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseImmediate(OperandVector &Operands);
OperandMatchResultTy parseRegister(OperandVector &Operands);
+ OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
bool parseOperand(OperandVector &Operands);
@@ -125,10 +130,57 @@ public:
return static_cast<const MCConstantExpr *>(Val)->getValue();
}
+ // Predicate methods for AsmOperands defined in RISCVInstrInfo.td
+
+ /// Return true if the operand is a valid for the fence instruction e.g.
+ /// ('iorw').
+ bool isFenceArg() const {
+ if (!isImm())
+ return false;
+ const MCExpr *Val = getImm();
+ auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
+ if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
+ return false;
+
+ StringRef Str = SVal->getSymbol().getName();
+ // Letters must be unique, taken from 'iorw', and in ascending order. This
+ // holds as long as each individual character is one of 'iorw' and is
+ // greater than the previous character.
+ char Prev = '\0';
+ for (char c : Str) {
+ if (c != 'i' && c != 'o' && c != 'r' && c != 'w')
+ return false;
+ if (c <= Prev)
+ return false;
+ Prev = c;
+ }
+ return true;
+ }
+
+ bool isUImm5() const {
+ return (isConstantImm() && isUInt<5>(getConstantImm()));
+ }
+
bool isSImm12() const {
return (isConstantImm() && isInt<12>(getConstantImm()));
}
+ bool isUImm12() const {
+ return (isConstantImm() && isUInt<12>(getConstantImm()));
+ }
+
+ bool isSImm13Lsb0() const {
+ return (isConstantImm() && isShiftedInt<12, 1>(getConstantImm()));
+ }
+
+ bool isUImm20() const {
+ return (isConstantImm() && isUInt<20>(getConstantImm()));
+ }
+
+ bool isSImm21Lsb0() const {
+ return (isConstantImm() && isShiftedInt<20, 1>(getConstantImm()));
+ }
+
/// getStartLoc - Gets location of the first token of this operand
SMLoc getStartLoc() const override { return StartLoc; }
/// getEndLoc - Gets location of the last token of this operand
@@ -208,6 +260,24 @@ public:
assert(N == 1 && "Invalid number of operands!");
addExpr(Inst, getImm());
}
+
+ void addFenceArgOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // isFenceArg has validated the operand, meaning this cast is safe
+ auto SE = cast<MCSymbolRefExpr>(getImm());
+
+ unsigned Imm = 0;
+ for (char c : SE->getSymbol().getName()) {
+ switch (c) {
+ default: llvm_unreachable("FenceArg must contain only [iorw]");
+ case 'i': Imm |= RISCVFenceField::I; break;
+ case 'o': Imm |= RISCVFenceField::O; break;
+ case 'r': Imm |= RISCVFenceField::R; break;
+ case 'w': Imm |= RISCVFenceField::W; break;
+ }
+ }
+ Inst.addOperand(MCOperand::createImm(Imm));
+ }
};
} // end anonymous namespace.
@@ -215,13 +285,19 @@ public:
#define GET_MATCHER_IMPLEMENTATION
#include "RISCVGenAsmMatcher.inc"
+bool RISCVAsmParser::generateImmOutOfRangeError(
+ OperandVector &Operands, uint64_t ErrorInfo, int Lower, int Upper,
+ Twine Msg = "immediate must be an integer in the range") {
+ SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+ return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]");
+}
+
bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out,
uint64_t &ErrorInfo,
bool MatchingInlineAsm) {
MCInst Inst;
- SMLoc ErrorLoc;
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
default:
@@ -234,8 +310,8 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(IDLoc, "instruction use requires an option to be enabled");
case Match_MnemonicFail:
return Error(IDLoc, "unrecognized instruction mnemonic");
- case Match_InvalidOperand:
- ErrorLoc = IDLoc;
+ case Match_InvalidOperand: {
+ SMLoc ErrorLoc = IDLoc;
if (ErrorInfo != ~0U) {
if (ErrorInfo >= Operands.size())
return Error(ErrorLoc, "too few operands for instruction");
@@ -245,10 +321,30 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
ErrorLoc = IDLoc;
}
return Error(ErrorLoc, "invalid operand for instruction");
+ }
+ case Match_InvalidUImm5:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
case Match_InvalidSImm12:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 11),
+ (1 << 11) - 1);
+ case Match_InvalidUImm12:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 12) - 1);
+ case Match_InvalidSImm13Lsb0:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
+ "immediate must be a multiple of 2 bytes in the range");
+ case Match_InvalidUImm20:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);
+ case Match_InvalidSImm21Lsb0:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
+ "immediate must be a multiple of 2 bytes in the range");
+ case Match_InvalidFenceArg: {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
- return Error(ErrorLoc,
- "immediate must be an integer in the range [-2048, 2047]");
+ return Error(
+ ErrorLoc,
+ "operand must be formed of letters selected in-order from 'iorw'");
+ }
}
llvm_unreachable("Unknown match type detected!");
@@ -292,6 +388,10 @@ OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands) {
}
OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
+ SMLoc S = getLoc();
+ SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+ const MCExpr *Res;
+
switch (getLexer().getKind()) {
default:
return MatchOperand_NoMatch;
@@ -300,16 +400,46 @@ OperandMatchResultTy RISCVAsmParser::parseImmediate(OperandVector &Operands) {
case AsmToken::Plus:
case AsmToken::Integer:
case AsmToken::String:
+ if (getParser().parseExpression(Res))
+ return MatchOperand_ParseFail;
+ break;
+ case AsmToken::Identifier: {
+ StringRef Identifier;
+ if (getParser().parseIdentifier(Identifier))
+ return MatchOperand_ParseFail;
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
+ Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
break;
}
+ }
- const MCExpr *IdVal;
- SMLoc S = getLoc();
- if (getParser().parseExpression(IdVal))
+ Operands.push_back(RISCVOperand::createImm(Res, S, E));
+ return MatchOperand_Success;
+}
+
+OperandMatchResultTy
+RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
+ if (getLexer().isNot(AsmToken::LParen)) {
+ Error(getLoc(), "expected '('");
return MatchOperand_ParseFail;
+ }
+
+ getParser().Lex(); // Eat '('
+ Operands.push_back(RISCVOperand::createToken("(", getLoc()));
+
+ if (parseRegister(Operands) != MatchOperand_Success) {
+ Error(getLoc(), "expected register");
+ return MatchOperand_ParseFail;
+ }
+
+ if (getLexer().isNot(AsmToken::RParen)) {
+ Error(getLoc(), "expected ')'");
+ return MatchOperand_ParseFail;
+ }
+
+ getParser().Lex(); // Eat ')'
+ Operands.push_back(RISCVOperand::createToken(")", getLoc()));
- SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
- Operands.push_back(RISCVOperand::createImm(IdVal, S, E));
return MatchOperand_Success;
}
@@ -322,8 +452,12 @@ bool RISCVAsmParser::parseOperand(OperandVector &Operands) {
return false;
// Attempt to parse token as an immediate
- if (parseImmediate(Operands) == MatchOperand_Success)
+ if (parseImmediate(Operands) == MatchOperand_Success) {
+ // Parse memory base register if present
+ if (getLexer().is(AsmToken::LParen))
+ return parseMemOpBaseReg(Operands) != MatchOperand_Success;
return false;
+ }
// Finally we have exhausted all options and must declare defeat.
Error(getLoc(), "unknown operand");
diff --git a/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp
index e55658e3968..6bc4ea2cd0d 100644
--- a/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp
+++ b/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "RISCVInstPrinter.h"
+#include "MCTargetDesc/RISCVBaseInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
@@ -53,3 +54,16 @@ void RISCVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
assert(MO.isExpr() && "Unknown operand kind in printOperand");
MO.getExpr()->print(O, &MAI);
}
+
+void RISCVInstPrinter::printFenceArg(const MCInst *MI, unsigned OpNo,
+ raw_ostream &O) {
+ unsigned FenceArg = MI->getOperand(OpNo).getImm();
+ if ((FenceArg & RISCVFenceField::I) != 0)
+ O << 'i';
+ if ((FenceArg & RISCVFenceField::O) != 0)
+ O << 'o';
+ if ((FenceArg & RISCVFenceField::R) != 0)
+ O << 'r';
+ if ((FenceArg & RISCVFenceField::W) != 0)
+ O << 'w';
+}
diff --git a/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.h b/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.h
index f378c6f18da..3bb4fa37f15 100644
--- a/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.h
+++ b/llvm/lib/Target/RISCV/InstPrinter/RISCVInstPrinter.h
@@ -32,6 +32,7 @@ public:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
const char *Modifier = nullptr);
+ void printFenceArg(const MCInst *MI, unsigned OpNo, raw_ostream &O);
// Autogenerated by tblgen.
void printInstruction(const MCInst *MI, raw_ostream &O);
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
new file mode 100644
index 00000000000..c3bf3213a98
--- /dev/null
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -0,0 +1,54 @@
+//===-- RISCVBaseInfo.h - Top level definitions for RISCV MC ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains small standalone enum definitions for the RISCV target
+// useful for the compiler back-end and the MC libraries.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H
+#define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H
+
+#include "RISCVMCTargetDesc.h"
+
+namespace llvm {
+
+// RISCVII - This namespace holds all of the target specific flags that
+// instruction info tracks. All definitions must match RISCVInstrFormats.td.
+namespace RISCVII {
+enum {
+ InstFormatPseudo = 0,
+ InstFormatR = 1,
+ InstFormatI = 2,
+ InstFormatS = 3,
+ InstFormatSB = 4,
+ InstFormatU = 5,
+ InstFormatOther = 6,
+
+ InstFormatMask = 15
+};
+enum {
+ MO_None,
+ MO_LO,
+ MO_HI,
+ MO_PCREL_HI,
+};
+} // namespace RISCVII
+
+// Describes the predecessor/successor bits used in the FENCE instruction.
+namespace RISCVFenceField {
+enum FenceField {
+ I = 8,
+ O = 4,
+ R = 2,
+ W = 1
+};
+}
+} // namespace llvm
+
+#endif
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index 9309d493cef..eb0beb028ad 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -55,6 +55,10 @@ public:
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+
+ unsigned getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
};
} // end anonymous namespace
@@ -88,4 +92,19 @@ RISCVMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
return 0;
}
+unsigned
+RISCVMCCodeEmitter::getImmOpValueAsr1(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpNo);
+
+ if (MO.isImm()) {
+ unsigned Res = MO.getImm();
+ assert((Res & 1) == 0 && "LSB is non-zero");
+ return Res >> 1;
+ }
+
+ llvm_unreachable("Unhandled expression!");
+}
+
#include "RISCVGenMCCodeEmitter.inc"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 93d13f79390..78b1c907f33 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -13,17 +13,59 @@
include "RISCVInstrFormats.td"
-class SImmAsmOperand<int width>
- : AsmOperandClass {
- let Name = "SImm" # width;
+class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
+ let Name = prefix # "Imm" # width # suffix;
let RenderMethod = "addImmOperands";
let DiagnosticType = !strconcat("Invalid", Name);
}
+class SImmAsmOperand<int width, string suffix = "">
+ : ImmAsmOperand<"S", width, suffix> {
+}
+
+class UImmAsmOperand<int width, string suffix = "">
+ : ImmAsmOperand<"U", width, suffix> {
+}
+
+def FenceArg : AsmOperandClass {
+ let Name = "FenceArg";
+ let RenderMethod = "addFenceArgOperands";
+ let DiagnosticType = "InvalidFenceArg";
+}
+
+def fencearg : Operand<i32> {
+ let ParserMatchClass = FenceArg;
+ let PrintMethod = "printFenceArg";
+}
+
+def uimm5 : Operand<i32> {
+ let ParserMatchClass = UImmAsmOperand<5>;
+}
+
def simm12 : Operand<i32> {
let ParserMatchClass = SImmAsmOperand<12>;
}
+def uimm12 : Operand<i32> {
+ let ParserMatchClass = UImmAsmOperand<12>;
+}
+
+// A 13-bit signed immediate where the least significant bit is zero.
+def simm13_lsb0 : Operand<i32> {
+ let ParserMatchClass = SImmAsmOperand<13, "Lsb0">;
+ let EncoderMethod = "getImmOpValueAsr1";
+}
+
+def uimm20 : Operand<i32> {
+ let ParserMatchClass = UImmAsmOperand<20>;
+}
+
+// A 21-bit signed immediate where the least significant bit is zero.
+def simm21_lsb0 : Operand<i32> {
+ let ParserMatchClass = SImmAsmOperand<21, "Lsb0">;
+ let EncoderMethod = "getImmOpValueAsr1";
+}
+
// As noted in RISCVRegisterInfo.td, the hope is that support for
// variable-sized register classes will mean that instruction definitions do
// not need to be duplicated for 32-bit and 64-bit register classes. For now
@@ -32,6 +74,52 @@ def simm12 : Operand<i32> {
// like <http://lists.llvm.org/pipermail/llvm-dev/2016-September/105027.html>
// is adopted.
+def LUI : FU<0b0110111, (outs GPR:$rd), (ins uimm20:$imm20),
+ "lui\t$rd, $imm20", []>;
+
+def AUIPC : FU<0b0010111, (outs GPR:$rd), (ins uimm20:$imm20),
+ "auipc\t$rd, $imm20", []>;
+
+def JAL : FUJ<0b1101111, (outs GPR:$rd), (ins simm21_lsb0:$imm20),
+ "jal\t$rd, $imm20", []>;
+
+def JALR : FI<0b000, 0b1100111, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
+ "jalr\t$rd, $rs1, $imm12", []>;
+
+class Bcc<bits<3> funct3, string OpcodeStr> :
+ FSB<funct3, 0b1100011, (outs), (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12),
+ OpcodeStr#"\t$rs1, $rs2, $imm12", []> {
+}
+
+def BEQ : Bcc<0b000, "beq">;
+def BNE : Bcc<0b001, "bne">;
+def BLT : Bcc<0b100, "blt">;
+def BGE : Bcc<0b101, "bge">;
+def BLTU : Bcc<0b110, "bltu">;
+def BGEU : Bcc<0b111, "bgeu">;
+
+class LD_ri<bits<3> funct3, string OpcodeStr> :
+ FI<funct3, 0b0000011, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
+ OpcodeStr#"\t$rd, ${imm12}(${rs1})", []> {
+ let mayLoad = 1;
+}
+
+def LB : LD_ri<0b000, "lb">;
+def LH : LD_ri<0b001, "lh">;
+def LW : LD_ri<0b010, "lw">;
+def LBU : LD_ri<0b100, "lbu">;
+def LHU : LD_ri<0b101, "lhu">;
+
+class ST_ri<bits<3> funct3, string OpcodeStr> :
+ FS<funct3, 0b0100011, (outs), (ins GPR:$rs1, GPR:$rs2, simm12:$imm12),
+ OpcodeStr#"\t$rs2, ${imm12}(${rs1})", []> {
+ let mayStore = 1;
+}
+
+def SB : ST_ri<0b000, "sb">;
+def SH : ST_ri<0b001, "sh">;
+def SW : ST_ri<0b010, "sw">;
+
class ALU_ri<bits<3> funct3, string OpcodeStr> :
FI<funct3, 0b0010011, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
OpcodeStr#"\t$rd, $rs1, $imm12", []>
@@ -45,6 +133,16 @@ def XORI : ALU_ri<0b100, "xori">;
def ORI : ALU_ri<0b110, "ori">;
def ANDI : ALU_ri<0b111, "andi">;
+class SHIFT32_ri<bit arithshift, bits<3> funct3, string OpcodeStr> :
+ FI32Shift<arithshift, funct3, 0b0010011, (outs GPR:$rd), (ins GPR:$rs1, uimm5:$shamt),
+ OpcodeStr#"\t$rd, $rs1, $shamt", []>
+{
+}
+
+def SLLI : SHIFT32_ri<0, 0b001, "slli">;
+def SRLI : SHIFT32_ri<0, 0b101, "srli">;
+def SRAI : SHIFT32_ri<1, 0b101, "srai">;
+
class ALU_rr<bits<7> funct7, bits<3> funct3, string OpcodeStr> :
FR<funct7, funct3, 0b0110011, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
OpcodeStr#"\t$rd, $rs1, $rs2", []>
@@ -62,3 +160,47 @@ def SRA : ALU_rr<0b0100000, 0b101, "sra">;
def OR : ALU_rr<0b0000000, 0b110, "or">;
def AND : ALU_rr<0b0000000, 0b111, "and">;
+def FENCE : FI<0b000, 0b0001111, (outs), (ins fencearg:$pred, fencearg:$succ),
+ "fence\t$pred, $succ", []> {
+ bits<4> pred;
+ bits<4> succ;
+
+ let rs1 = 0;
+ let rd = 0;
+ let imm12 = {0b0000,pred,succ};
+}
+
+def FENCEI : FI<0b001, 0b0001111, (outs), (ins), "fence.i", []> {
+ let rs1 = 0;
+ let rd = 0;
+ let imm12 = 0;
+}
+
+let rs1=0, rd=0 in {
+ def ECALL : FI<0b000, 0b1110011, (outs), (ins), "ecall", []> {
+ let imm12=0;
+ }
+ def EBREAK : FI<0b000, 0b1110011, (outs), (ins), "ebreak", []> {
+ let imm12=1;
+ }
+}
+
+class CSR_rr<bits<3> funct3, string OpcodeStr> :
+ FI<funct3, 0b1110011, (outs GPR:$rd), (ins uimm12:$imm12, GPR:$rs1),
+ OpcodeStr#"\t$rd, $imm12, $rs1", []>
+{
+}
+
+def CSRRW : CSR_rr<0b001, "csrrw">;
+def CSRRS : CSR_rr<0b010, "csrrs">;
+def CSRRC : CSR_rr<0b011, "csrrc">;
+
+class CSR_ri<bits<3> funct3, string OpcodeStr> :
+ FI<funct3, 0b1110011, (outs GPR:$rd), (ins uimm12:$imm12, uimm5:$rs1),
+ OpcodeStr#"\t$rd, $imm12, $rs1", []>
+{
+}
+
+def CSRRWI : CSR_ri<0b101, "csrrwi">;
+def CSRRSI : CSR_ri<0b110, "csrrsi">;
+def CSRRCI : CSR_ri<0b111, "csrrci">;
OpenPOWER on IntegriCloud