summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorAlex Bradbury <asb@lowrisc.org>2017-11-09 15:00:03 +0000
committerAlex Bradbury <asb@lowrisc.org>2017-11-09 15:00:03 +0000
commit8c345c5aa903b67bdf43394f05205a09c50f6dce (patch)
tree43678bf3965f191557dade2b8254ea1a286198d9 /llvm/lib
parent89d31658e5601c8a9a7737db64e239c1efcc5d6b (diff)
downloadbcm5719-llvm-8c345c5aa903b67bdf43394f05205a09c50f6dce.tar.gz
bcm5719-llvm-8c345c5aa903b67bdf43394f05205a09c50f6dce.zip
[RISCV] MC layer support for the standard RV32A instruction set extension
llvm-svn: 317791
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp37
-rw-r--r--llvm/lib/Target/RISCV/RISCV.td17
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrFormats.td18
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfo.td1
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoA.td63
-rw-r--r--llvm/lib/Target/RISCV/RISCVSubtarget.h4
6 files changed, 128 insertions, 12 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 486784859bd..3f76ce3b24a 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -52,7 +52,8 @@ class RISCVAsmParser : public MCTargetAsmParser {
#include "RISCVGenAsmMatcher.inc"
OperandMatchResultTy parseImmediate(OperandVector &Operands);
- OperandMatchResultTy parseRegister(OperandVector &Operands);
+ OperandMatchResultTy parseRegister(OperandVector &Operands,
+ bool AllowParens = false);
OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
@@ -431,9 +432,20 @@ bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
return Error(StartLoc, "invalid register name");
}
-OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands) {
- SMLoc S = getLoc();
- SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
+OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
+ bool AllowParens) {
+ SMLoc FirstS = getLoc();
+ bool HadParens = false;
+ AsmToken Buf[2];
+
+ // If this a parenthesised register name is allowed, parse it atomically
+ if (AllowParens && getLexer().is(AsmToken::LParen)) {
+ size_t ReadCount = getLexer().peekTokens(Buf);
+ if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) {
+ HadParens = true;
+ getParser().Lex(); // Eat '('
+ }
+ }
switch (getLexer().getKind()) {
default:
@@ -443,12 +455,25 @@ OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands) {
unsigned RegNo = MatchRegisterName(Name);
if (RegNo == 0) {
RegNo = MatchRegisterAltName(Name);
- if (RegNo == 0)
+ if (RegNo == 0) {
+ if (HadParens)
+ getLexer().UnLex(Buf[0]);
return MatchOperand_NoMatch;
+ }
}
+ if (HadParens)
+ Operands.push_back(RISCVOperand::createToken("(", FirstS));
+ SMLoc S = getLoc();
+ SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1);
getLexer().Lex();
Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
}
+
+ if (HadParens) {
+ getParser().Lex(); // Eat ')'
+ Operands.push_back(RISCVOperand::createToken(")", getLoc()));
+ }
+
return MatchOperand_Success;
}
@@ -555,7 +580,7 @@ RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
/// If operand was parsed, returns false, else true.
bool RISCVAsmParser::parseOperand(OperandVector &Operands) {
// Attempt to parse token as register
- if (parseRegister(Operands) == MatchOperand_Success)
+ if (parseRegister(Operands, true) == MatchOperand_Success)
return false;
// Attempt to parse token as an immediate
diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td
index d8581f8d03c..63d2b827014 100644
--- a/llvm/lib/Target/RISCV/RISCV.td
+++ b/llvm/lib/Target/RISCV/RISCV.td
@@ -13,13 +13,20 @@ include "llvm/Target/Target.td"
// RISC-V subtarget features and instruction predicates.
//===----------------------------------------------------------------------===//
-def FeatureStdExtM : SubtargetFeature<"m", "HasStdExtM", "true",
- "'M' (Integer Multiplication and Division)">;
-def HasStdExtM : Predicate<"Subtarget->hasStdExtM()">,
+def FeatureStdExtM
+ : SubtargetFeature<"m", "HasStdExtM", "true",
+ "'M' (Integer Multiplication and Division)">;
+def HasStdExtM : Predicate<"Subtarget->hasStdExtM()">,
AssemblerPredicate<"FeatureStdExtM">;
-def Feature64Bit : SubtargetFeature<"64bit", "HasRV64", "true",
- "Implements RV64">;
+def FeatureStdExtA
+ : SubtargetFeature<"a", "HasStdExtA", "true",
+ "'A' (Atomic Instructions)">;
+def HasStdExtA : Predicate<"Subtarget->hasStdExtA()">,
+ AssemblerPredicate<"FeatureStdExtA">;
+
+def Feature64Bit
+ : SubtargetFeature<"64bit", "HasRV64", "true", "Implements RV64">;
def RV64 : HwMode<"+64bit">;
def RV32 : HwMode<"-64bit">;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
index 48f6cf8762d..3dca957e31f 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
@@ -118,6 +118,24 @@ class RVInstR<bits<7> funct7, bits<3> funct3, RISCVOpcode opcode, dag outs,
let Opcode = opcode.Value;
}
+class RVInstRAtomic<bits<5> funct5, bit aq, bit rl, bits<3> funct3,
+ RISCVOpcode opcode, dag outs, dag ins, string opcodestr,
+ string argstr>
+ : RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+ bits<5> rs2;
+ bits<5> rs1;
+ bits<5> rd;
+
+ let Inst{31-27} = funct5;
+ let Inst{26} = aq;
+ let Inst{25} = rl;
+ let Inst{24-20} = rs2;
+ let Inst{19-15} = rs1;
+ let Inst{14-12} = funct3;
+ let Inst{11-7} = rd;
+ let Opcode = opcode.Value;
+}
+
class RVInstI<bits<3> funct3, RISCVOpcode opcode, dag outs, dag ins,
string opcodestr, string argstr>
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatI> {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index e95a8e1c813..d2b509e660c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -405,3 +405,4 @@ def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
//===----------------------------------------------------------------------===//
include "RISCVInstrInfoM.td"
+include "RISCVInstrInfoA.td"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
new file mode 100644
index 00000000000..54f35c3c0ba
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td
@@ -0,0 +1,63 @@
+//===-- RISCVInstrInfoA.td - RISC-V 'A' instructions -------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the RISC-V instructions from the standard 'A', Atomic
+// Instructions extension.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instruction class templates
+//===----------------------------------------------------------------------===//
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+class LR_r<bit aq, bit rl, bits<3> funct3, string opcodestr>
+ : RVInstRAtomic<0b00010, aq, rl, funct3, OPC_AMO,
+ (outs GPR:$rd), (ins GPR:$rs1),
+ opcodestr, "$rd, (${rs1})"> {
+ let rs2 = 0;
+}
+
+multiclass LR_r_aq_rl<bits<3> funct3, string opcodestr> {
+ def "" : LR_r<0, 0, funct3, opcodestr>;
+ def _AQ : LR_r<1, 0, funct3, opcodestr # ".aq">;
+ def _RL : LR_r<0, 1, funct3, opcodestr # ".rl">;
+ def _AQ_RL : LR_r<1, 1, funct3, opcodestr # ".aqrl">;
+}
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in
+class AMO_rr<bits<5> funct5, bit aq, bit rl, bits<3> funct3, string opcodestr>
+ : RVInstRAtomic<funct5, aq, rl, funct3, OPC_AMO,
+ (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
+ opcodestr, "$rd, $rs2, (${rs1})">;
+
+multiclass AMO_rr_aq_rl<bits<5> funct5, bits<3> funct3, string opcodestr> {
+ def "" : AMO_rr<funct5, 0, 0, funct3, opcodestr>;
+ def _AQ : AMO_rr<funct5, 1, 0, funct3, opcodestr # ".aq">;
+ def _RL : AMO_rr<funct5, 0, 1, funct3, opcodestr # ".rl">;
+ def _AQ_RL : AMO_rr<funct5, 1, 1, funct3, opcodestr # ".aqrl">;
+}
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasStdExtA] in {
+defm LR_W : LR_r_aq_rl<0b010, "lr.w">;
+defm SC_W : AMO_rr_aq_rl<0b00011, 0b010, "sc.w">;
+defm AMOSWAP_W : AMO_rr_aq_rl<0b00001, 0b010, "amoswap.w">;
+defm AMOADD_W : AMO_rr_aq_rl<0b00000, 0b010, "amoadd.w">;
+defm AMOXOR_W : AMO_rr_aq_rl<0b00100, 0b010, "amoxor.w">;
+defm AMOAND_W : AMO_rr_aq_rl<0b01100, 0b010, "amoand.w">;
+defm AMOOR_W : AMO_rr_aq_rl<0b01000, 0b010, "amoor.w">;
+defm AMOMIN_W : AMO_rr_aq_rl<0b10000, 0b010, "amomin.w">;
+defm AMOMAX_W : AMO_rr_aq_rl<0b10100, 0b010, "amomax.w">;
+defm AMOMINU_W : AMO_rr_aq_rl<0b11000, 0b010, "amominu.w">;
+defm AMOMAXU_W : AMO_rr_aq_rl<0b11100, 0b010, "amomaxu.w">;
+} // Predicates = [HasStdExtA]
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h
index be9b04990ca..14b25c14dbe 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -30,7 +30,8 @@ class StringRef;
class RISCVSubtarget : public RISCVGenSubtargetInfo {
virtual void anchor();
- bool HasStdExtM;
+ bool HasStdExtM = false;
+ bool HasStdExtA = false;
bool HasRV64 = false;
unsigned XLen = 32;
MVT XLenVT = MVT::i32;
@@ -68,6 +69,7 @@ public:
return &TSInfo;
}
bool hasStdExtM() const { return HasStdExtM; }
+ bool hasStdExtA() const { return HasStdExtA; }
bool is64Bit() const { return HasRV64; }
MVT getXLenVT() const { return XLenVT; }
unsigned getXLen() const { return XLen; }
OpenPOWER on IntegriCloud