public:
enum MipsMatchResultTy {
- Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY
+ Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "MipsGenAsmMatcher.inc"
#undef GET_OPERAND_DIAGNOSTIC_TYPES
Inst.addOperand(MCOperand::createReg(getHWRegsReg()));
}
+ template <unsigned Bits>
+ void addConstantUImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ uint64_t Imm = getConstantImm() & ((1 << Bits) - 1);
+ Inst.addOperand(MCOperand::createImm(Imm));
+ }
+
void addImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCExpr *Expr = getImm();
bool isConstantImm() const {
return isImm() && dyn_cast<MCConstantExpr>(getImm());
}
+ bool isConstantImmz() const {
+ return isConstantImm() && getConstantImm() == 0;
+ }
template <unsigned Bits> bool isUImm() const {
return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm());
}
return Match_Success;
}
+static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
+ uint64_t ErrorInfo) {
+ if (ErrorInfo != ~0ULL && ErrorInfo < Operands.size()) {
+ SMLoc ErrorLoc = Operands[ErrorInfo]->getStartLoc();
+ if (ErrorLoc == SMLoc())
+ return Loc;
+ return ErrorLoc;
+ }
+ return Loc;
+}
+
bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out,
if (ErrorInfo >= Operands.size())
return Error(IDLoc, "too few operands for instruction");
- ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
+ ErrorLoc = Operands[ErrorInfo]->getStartLoc();
if (ErrorLoc == SMLoc())
ErrorLoc = IDLoc;
}
return Error(IDLoc, "invalid instruction");
case Match_RequiresDifferentSrcAndDst:
return Error(IDLoc, "source and destination must be different");
+ case Match_Immz:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
}
llvm_unreachable("Implement any new match types added!");
// Mips Operand, Complex Patterns and Transformations Definitions.
//===----------------------------------------------------------------------===//
+def ConstantImmzAsmOperandClass : AsmOperandClass {
+ let Name = "ConstantImmz";
+ let RenderMethod = "addConstantUImmOperands<1>";
+ let PredicateMethod = "isConstantImmz";
+ let SuperClasses = [];
+ let DiagnosticType = "Immz";
+}
+
def MipsJumpTargetAsmOperand : AsmOperandClass {
let Name = "JumpTarget";
let ParserMethod = "parseJumpTarget";
// Zero
def uimmz : Operand<i32> {
let PrintMethod = "printUnsignedImm";
+ let ParserMatchClass = ConstantImmzAsmOperandClass;
}
// Unsigned Operand
--- /dev/null
+# Instructions that are invalid
+#
+# RUN: not llvm-mc %s -triple=mips-unknown-linux -mcpu=mips32r2 -mattr=+msa \
+# RUN: -show-encoding 2>%t1
+# RUN: FileCheck %s < %t1
+
+ .set noat
+ insve.b $w25[3], $w9[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+ insve.h $w24[2], $w2[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+ insve.w $w0[2], $w13[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+ insve.d $w3[0], $w18[1] # CHECK: :[[@LINE]]:26: error: expected '0'
--- /dev/null
+# Instructions that are invalid
+#
+# RUN: not llvm-mc %s -triple=mips-unknown-linux -mcpu=mips32r2 -mattr=+msa \
+# RUN: -show-encoding 2>%t1
+# RUN: FileCheck %s < %t1
+
+ .set noat
+ insve.b $w25[3], $w9[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+ insve.h $w24[2], $w2[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+ insve.w $w0[2], $w13[1] # CHECK: :[[@LINE]]:26: error: expected '0'
+ insve.d $w3[0], $w18[1] # CHECK: :[[@LINE]]:26: error: expected '0'