summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
diff options
context:
space:
mode:
authorAlex Bradbury <asb@lowrisc.org>2017-12-07 10:26:05 +0000
committerAlex Bradbury <asb@lowrisc.org>2017-12-07 10:26:05 +0000
commit0d6cf90663e6662e9b7b6045d56755679c1ffdc9 (patch)
treebb2afe7a44942e06378623f5603275e9355d38be /llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
parent293da70b831f635be52ccf7fc79fb4c483623046 (diff)
downloadbcm5719-llvm-0d6cf90663e6662e9b7b6045d56755679c1ffdc9.tar.gz
bcm5719-llvm-0d6cf90663e6662e9b7b6045d56755679c1ffdc9.zip
[RISCV] MC layer support for the standard RV32F instruction set extension
The most interesting part of this patch is probably the handling of rounding mode arguments. Sadly, the RISC-V assembler handles floating point rounding modes as a special "argument" when it would be more consistent to handle them like the atomics, opcode suffixes. This patch supports parsing this optional parameter, using InstAlias to allow parsing these floating point instructions when no rounding mode is specified. Differential Revision: https://reviews.llvm.org/D39893 llvm-svn: 320020
Diffstat (limited to 'llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp')
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp36
1 files changed, 36 insertions, 0 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 3f76ce3b24a..0037d8d8af4 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -185,6 +185,20 @@ public:
return true;
}
+ /// Return true if the operand is a valid floating point rounding mode.
+ bool isFRMArg() 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();
+
+ return RISCVFPRndMode::stringToRoundingMode(Str) != RISCVFPRndMode::Invalid;
+ }
+
bool isUImm5() const {
int64_t Imm;
RISCVMCExpr::VariantKind VK;
@@ -344,6 +358,22 @@ public:
}
Inst.addOperand(MCOperand::createImm(Imm));
}
+
+ // Returns the rounding mode represented by this RISCVOperand. Should only
+ // be called after checking isFRMArg.
+ RISCVFPRndMode::RoundingMode getRoundingMode() const {
+ // isFRMArg has validated the operand, meaning this cast is safe.
+ auto SE = cast<MCSymbolRefExpr>(getImm());
+ RISCVFPRndMode::RoundingMode FRM =
+ RISCVFPRndMode::stringToRoundingMode(SE->getSymbol().getName());
+ assert(FRM != RISCVFPRndMode::Invalid && "Invalid rounding mode");
+ return FRM;
+ }
+
+ void addFRMArgOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createImm(getRoundingMode()));
+ }
};
} // end anonymous namespace.
@@ -411,6 +441,12 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
ErrorLoc,
"operand must be formed of letters selected in-order from 'iorw'");
}
+ case Match_InvalidFRMArg: {
+ SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+ return Error(
+ ErrorLoc,
+ "operand must be a valid floating point rounding mode mnemonic");
+ }
}
llvm_unreachable("Unknown match type detected!");
OpenPOWER on IntegriCloud