diff options
| author | Daniel Sanders <daniel.sanders@imgtec.com> | 2015-11-06 12:22:31 +0000 |
|---|---|---|
| committer | Daniel Sanders <daniel.sanders@imgtec.com> | 2015-11-06 12:22:31 +0000 |
| commit | ea4f653d18e74439f0abefe5861d05fea9ddf5d0 (patch) | |
| tree | 2495edb31781be386dad08dbf3873d7d3585c77a /llvm/lib/Target/Mips/AsmParser | |
| parent | 52da7af4d2ae4b559de3a8bfdffdfa01581e67bd (diff) | |
| download | bcm5719-llvm-ea4f653d18e74439f0abefe5861d05fea9ddf5d0.tar.gz bcm5719-llvm-ea4f653d18e74439f0abefe5861d05fea9ddf5d0.zip | |
[mips][ias] Range check uimm2 operands and fix a bug this revealed.
Summary:
The bug was that the MIPS32R6/MIPS64R6/microMIPS32R6 versions of LSA and DLSA
(unlike the MSA version) failed to account for the off-by-one encoding of the
immediate. The range is actually 1..4 rather than 0..3.
Reviewers: vkalintiris
Subscribers: atanasyan, dsanders, llvm-commits
Differential Revision: http://reviews.llvm.org/D14015
llvm-svn: 252295
Diffstat (limited to 'llvm/lib/Target/Mips/AsmParser')
| -rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 09ae6a5d43c..aea022a336f 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -387,7 +387,6 @@ public: #define GET_OPERAND_DIAGNOSTIC_TYPES #include "MipsGenAsmMatcher.inc" #undef GET_OPERAND_DIAGNOSTIC_TYPES - }; MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, @@ -894,10 +893,12 @@ public: Inst.addOperand(MCOperand::createReg(getHWRegsReg())); } - template <unsigned Bits> + template <unsigned Bits, int Offset = 0> void addConstantUImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - uint64_t Imm = getConstantImm() & ((1 << Bits) - 1); + uint64_t Imm = getConstantImm() - Offset; + Imm &= (1 << Bits) - 1; + Imm += Offset; Inst.addOperand(MCOperand::createImm(Imm)); } @@ -963,6 +964,9 @@ public: bool isConstantImmz() const { return isConstantImm() && getConstantImm() == 0; } + template <unsigned Bits, int Offset = 0> bool isConstantUImm() const { + return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset); + } template <unsigned Bits> bool isUImm() const { return isImm() && isConstantImm() && isUInt<Bits>(getConstantImm()); } @@ -3296,6 +3300,12 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return Error(IDLoc, "source and destination must be different"); case Match_Immz: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'"); + case Match_UImm2_0: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 2-bit unsigned immediate"); + case Match_UImm2_1: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected immediate in range 1 .. 4"); } llvm_unreachable("Implement any new match types added!"); |

