[mips] Range check simm7.
Summary:
Also renamed li_simm7 to li16_imm since it's not a simm7 and has an unusual
encoding (it's a uimm7 except that 0x7f represents -1).
Reviewers: vkalintiris
Subscribers: dsanders, llvm-commits
Differential Revision: http://reviews.llvm.org/D18145
llvm-svn: 264056
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 41d8d24..1a1682d 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -1080,6 +1080,11 @@
return isConstantImm() &&
isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
}
+ template <unsigned Bits, unsigned ShiftLeftAmount>
+ bool isScaledSImm() const {
+ return isConstantImm() &&
+ isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
+ }
bool isRegList16() const {
if (!isRegList())
return false;
@@ -3764,6 +3769,12 @@
case Match_UImm7_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 7-bit unsigned immediate");
+ case Match_UImm7_N1:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected immediate in range -1 .. 126");
+ case Match_SImm7_Lsl2:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected both 9-bit signed immediate and multiple of 4");
case Match_UImm8_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 8-bit unsigned immediate");
diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index a82d8f3..e2d96ff 100644
--- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -362,7 +362,7 @@
uint64_t Address,
const void *Decoder);
-static DecodeStatus DecodeLiSimm7(MCInst &Inst,
+static DecodeStatus DecodeLi16Imm(MCInst &Inst,
unsigned Value,
uint64_t Address,
const void *Decoder);
@@ -390,9 +390,10 @@
Decoder);
}
-template <unsigned Bits, int Offset = 0>
-static DecodeStatus DecodeSImmWithOffset(MCInst &Inst, unsigned Value,
- uint64_t Address, const void *Decoder);
+template <unsigned Bits, int Offset = 0, int ScaleBy = 1>
+static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value,
+ uint64_t Address,
+ const void *Decoder);
static DecodeStatus DecodeInsSize(MCInst &Inst,
unsigned Insn,
@@ -1897,7 +1898,7 @@
return MCDisassembler::Success;
}
-static DecodeStatus DecodeLiSimm7(MCInst &Inst,
+static DecodeStatus DecodeLi16Imm(MCInst &Inst,
unsigned Value,
uint64_t Address,
const void *Decoder) {
@@ -1934,11 +1935,11 @@
return MCDisassembler::Success;
}
-template <unsigned Bits, int Offset>
-static DecodeStatus DecodeSImmWithOffset(MCInst &Inst, unsigned Value,
- uint64_t Address,
- const void *Decoder) {
- int32_t Imm = SignExtend32<Bits>(Value);
+template <unsigned Bits, int Offset, int ScaleBy>
+static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value,
+ uint64_t Address,
+ const void *Decoder) {
+ int32_t Imm = SignExtend32<Bits>(Value) * ScaleBy;
Inst.addOperand(MCOperand::createImm(Imm + Offset));
return MCDisassembler::Success;
}
diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
index 69bdfa0..5e2d7df 100644
--- a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td
@@ -821,7 +821,7 @@
MMR6Arch<"srl16">;
class BREAK16_MMR6_DESC : BrkSdbbp16MM<"break16">, MMR6Arch<"srl16">,
MicroMipsR6Inst16;
-class LI16_MMR6_DESC : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>,
+class LI16_MMR6_DESC : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>,
MMR6Arch<"srl16">, MicroMipsR6Inst16, IsAsCheapAsAMove;
class MOVE16_MMR6_DESC : MoveMM16<"move16", GPR32Opnd>, MMR6Arch<"srl16">,
MicroMipsR6Inst16;
diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
index e218265..0fe9b24 100644
--- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
@@ -1,11 +1,6 @@
def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddrMM", [frameindex]>;
def addrimm4lsl2 : ComplexPattern<iPTR, 2, "selectIntAddrLSL2MM", [frameindex]>;
-def simm7 : Operand<i32>;
-def li_simm7 : Operand<i32> {
- let DecoderMethod = "DecodeLiSimm7";
-}
-
def simm12 : Operand<i32> {
let DecoderMethod = "DecodeSimm12";
}
@@ -88,7 +83,7 @@
def mem_mm_gp_imm7_lsl2 : Operand<i32> {
let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops GPRMM16:$base, simm7:$offset);
+ let MIOperandInfo = (ops GPRMM16:$base, simm7_lsl2:$offset);
let OperandType = "OPERAND_MEMORY";
let EncoderMethod = "getMemEncodingMMGPImm7Lsl2";
}
@@ -621,7 +616,7 @@
def MFLO16_MM : MoveFromHILOMM<"mflo", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x12>;
def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>;
def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMoveP>, MOVEP_FM_MM16;
-def LI16_MM : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>, LI_FM_MM16,
+def LI16_MM : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, LI_FM_MM16,
IsAsCheapAsAMove;
def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>,
ISA_MICROMIPS32_NOT_MIPS32R6;
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td
index 3de2999..c97f0b4 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -461,10 +461,23 @@
: UImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]>;
def ConstantUImm10AsmOperandClass
: ConstantUImmAsmOperandClass<10, [UImm16AsmOperandClass]>;
+def ConstantSImm7Lsl2AsmOperandClass : AsmOperandClass {
+ let Name = "SImm7Lsl2";
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isScaledSImm<7, 2>";
+ let SuperClasses = [ConstantUImm10AsmOperandClass];
+ let DiagnosticType = "SImm7_Lsl2";
+}
def ConstantUImm8AsmOperandClass
- : ConstantUImmAsmOperandClass<8, [ConstantUImm10AsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<8, [ConstantSImm7Lsl2AsmOperandClass]>;
+def ConstantUImm7Sub1AsmOperandClass
+ : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass], -1> {
+ // Specify the names since the -1 offset causes invalid identifiers otherwise.
+ let Name = "UImm7_N1";
+ let DiagnosticType = "UImm7_N1";
+}
def ConstantUImm7AsmOperandClass
- : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<7, [ConstantUImm7Sub1AsmOperandClass]>;
def ConstantUImm6Lsl2AsmOperandClass : AsmOperandClass {
let Name = "UImm6Lsl2";
let RenderMethod = "addImmOperands";
@@ -728,11 +741,23 @@
// Signed operands
foreach I = {4, 5} in
def simm # I : Operand<i32> {
- let DecoderMethod = "DecodeSImmWithOffset<" # I # ">";
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">";
let ParserMatchClass =
!cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass");
}
+def simm7_lsl2 : Operand<OtherVT> {
+ let EncoderMethod = "getSImm7Lsl2Encoding";
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ", 0, 4>";
+ let ParserMatchClass = ConstantSImm7Lsl2AsmOperandClass;
+}
+
+// This is almost the same as a uimm7 but 0x7f is interpreted as -1.
+def li16_imm : Operand<i32> {
+ let DecoderMethod = "DecodeLi16Imm";
+ let ParserMatchClass = ConstantUImm7Sub1AsmOperandClass;
+}
+
def pcrel16 : Operand<i32> {
}