unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
unsigned Kind) override;
+ unsigned checkTargetMatchPredicate(MCInst &Inst) override;
bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo,
int64_t Lower, int64_t Upper, Twine Msg);
public:
enum RISCVMatchResultTy {
Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY,
+ Match_RequiresEvenGPRs,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "RISCVGenAsmMatcher.inc"
#undef GET_OPERAND_DIAGNOSTIC_TYPES
struct RegOp {
MCRegister RegNum;
- bool IsRV64;
bool IsGPRAsFPR;
};
bool isGPRAsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
- bool isGPRF64AsFPR() const { return isGPR() && Reg.IsGPRAsFPR && Reg.IsRV64; }
+ bool isGPRF64AsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
- bool isGPRPF64AsFPR() const {
- return isGPR() && Reg.IsGPRAsFPR && !Reg.IsRV64 &&
- !((Reg.RegNum - RISCV::X0) & 1);
- }
+ bool isGPRPF64AsFPR() const { return isGPR() && Reg.IsGPRAsFPR; }
static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm,
RISCVMCExpr::VariantKind &VK) {
return Op;
}
- static std::unique_ptr<RISCVOperand> createReg(unsigned RegNo, SMLoc S,
- SMLoc E, bool IsRV64,
- bool IsGPRAsFPR = false) {
+ static std::unique_ptr<RISCVOperand>
+ createReg(unsigned RegNo, SMLoc S, SMLoc E, bool IsGPRAsFPR = false) {
auto Op = std::make_unique<RISCVOperand>(KindTy::Register);
Op->Reg.RegNum = RegNo;
- Op->Reg.IsRV64 = IsRV64;
Op->Reg.IsGPRAsFPR = IsGPRAsFPR;
Op->StartLoc = S;
Op->EndLoc = E;
return Match_InvalidOperand;
}
+unsigned RISCVAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
+ const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
+
+ for (unsigned I = 0; I < MCID.NumOperands; ++I) {
+ if (MCID.operands()[I].RegClass == RISCV::GPRPF64RegClassID) {
+ const auto &Op = Inst.getOperand(I);
+ assert(Op.isReg());
+
+ MCRegister Reg = Op.getReg();
+ if (((Reg.id() - RISCV::X0) & 1) != 0)
+ return Match_RequiresEvenGPRs;
+ }
+ }
+
+ return Match_Success;
+}
+
bool RISCVAsmParser::generateImmOutOfRangeError(
OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper,
Twine Msg = "immediate must be an integer in the range") {
switch (Result) {
default:
break;
+ case Match_RequiresEvenGPRs:
+ return Error(IDLoc,
+ "double precision floating point operands must use even "
+ "numbered X register");
case Match_InvalidImmXLenLI:
if (isRV64()) {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
SMLoc S = getLoc();
SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
getLexer().Lex();
- Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
+ Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
}
if (HadParens) {
SMLoc S = getLoc();
SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
getLexer().Lex();
- Operands.push_back(RISCVOperand::createReg(RegNo, S, E, isRV64()));
+ Operands.push_back(RISCVOperand::createReg(RegNo, S, E));
return MatchOperand_Success;
}
SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size());
getLexer().Lex();
Operands.push_back(RISCVOperand::createReg(
- RegNo, S, E, isRV64(), !getSTI().hasFeature(RISCV::FeatureStdExtF)));
+ RegNo, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF)));
return MatchOperand_Success;
}
std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),
- llvm::SMLoc(), isRV64());
+ llvm::SMLoc());
}
std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultFRMArgOp() const {
# CHECK-ASM-AND-OBJ: fcvt.l.d a0, t0, dyn
# CHECK-ASM: encoding: [0x53,0xf5,0x22,0xc2]
-# CHECK-RV32: :[[#@LINE+1]]:14: error: invalid operand for instruction
+# CHECK-RV32: :[[#@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
fcvt.l.d a0, t0, dyn
# CHECK-ASM-AND-OBJ: fcvt.lu.d a1, t1, dyn
# CHECK-ASM: encoding: [0xd3,0x75,0x33,0xc2]
-# CHECK-RV32: :[[#@LINE+1]]:15: error: invalid operand for instruction
+# CHECK-RV32: :[[#@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
fcvt.lu.d a1, t1, dyn
# CHECK-ASM-AND-OBJ: fcvt.d.l t3, a3, dyn
# CHECK-ASM: encoding: [0x53,0xfe,0x26,0xd2]
-# CHECK-RV32: :[[#@LINE+1]]:10: error: invalid operand for instruction
+# CHECK-RV32: :[[#@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
fcvt.d.l t3, a3, dyn
# CHECK-ASM-AND-OBJ: fcvt.d.lu t4, a4, dyn
# CHECK-ASM: encoding: [0xd3,0x7e,0x37,0xd2]
-# CHECK-RV32: :[[#@LINE+1]]:11: error: invalid operand for instruction
+# CHECK-RV32: :[[#@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
fcvt.d.lu t4, a4, dyn
# Rounding modes
# CHECK-ASM-AND-OBJ: fcvt.d.l t3, a3, rne
# CHECK-ASM: encoding: [0x53,0x8e,0x26,0xd2]
-# CHECK-RV32: :[[#@LINE+1]]:10: error: invalid operand for instruction
+# CHECK-RV32: :[[#@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
fcvt.d.l t3, a3, rne
# CHECK-ASM-AND-OBJ: fcvt.d.lu t4, a4, rtz
# CHECK-ASM: encoding: [0xd3,0x1e,0x37,0xd2]
-# CHECK-RV32: :[[#@LINE+1]]:11: error: invalid operand for instruction
+# CHECK-RV32: :[[#@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
fcvt.d.lu t4, a4, rtz
# CHECK-ASM-AND-OBJ: fcvt.l.d a0, t0, rdn
# CHECK-ASM: encoding: [0x53,0xa5,0x22,0xc2]
-# CHECK-RV32: :[[#@LINE+1]]:14: error: invalid operand for instruction
+# CHECK-RV32: :[[#@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
fcvt.l.d a0, t0, rdn
# CHECK-ASM-AND-OBJ: fcvt.lu.d a1, t1, rup
# CHECK-ASM: encoding: [0xd3,0x35,0x33,0xc2]
-# CHECK-RV32: :[[#@LINE+1]]:15: error: invalid operand for instruction
+# CHECK-RV32: :[[#@LINE+1]]:1: error: instruction requires the following: RV64I Base Instruction Set
fcvt.lu.d a1, t1, rup