[mips][microMIPS] Implement DINSU, DINSM, DINS instructions
Differential Revision: http://reviews.llvm.org/D16181
llvm-svn: 261860
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index b1f9d20..5b1b65f 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -1032,6 +1032,10 @@
template <unsigned Bits> bool isConstantSImm() const {
return isConstantImm() && isInt<Bits>(getConstantImm());
}
+ template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
+ return isConstantImm() && getConstantImm() >= Bottom &&
+ getConstantImm() <= Top;
+ }
bool isToken() const override {
// Note: It's not possible to pretend that other operand kinds are tokens.
// The matcher emitter checks tokens first.
@@ -3749,6 +3753,9 @@
case Match_UImm5_Lsl2:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected both 7-bit unsigned immediate and multiple of 4");
+ case Match_UImmRange2_64:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected immediate in range 2 .. 64");
case Match_UImm6_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 6-bit unsigned immediate");
diff --git a/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
index ec1aef8..ffbcf40 100644
--- a/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
@@ -28,6 +28,9 @@
class DMOD_MM64R6_ENC : POOL32A_DIVMOD_FM_MMR6<"dmod", 0b101011000>;
class DDIVU_MM64R6_ENC : POOL32A_DIVMOD_FM_MMR6<"ddivu", 0b110011000>;
class DMODU_MM64R6_ENC : POOL32A_DIVMOD_FM_MMR6<"dmodu", 0b111011000>;
+class DINSU_MM64R6_ENC : POOL32S_EXTBITS_FM_MMR6<0b110100>;
+class DINSM_MM64R6_ENC : POOL32S_EXTBITS_FM_MMR6<0b000100>;
+class DINS_MM64R6_ENC : POOL32S_EXTBITS_FM_MMR6<0b001100>;
//===----------------------------------------------------------------------===//
//
@@ -90,6 +93,12 @@
class DDIVU_MM64R6_DESC : ArithLogicR<"ddivu", GPR32Opnd>;
class DMODU_MM64R6_DESC : ArithLogicR<"dmodu", GPR32Opnd>;
+class DINSU_MM64R6_DESC : InsBase<"dinsu", GPR64Opnd, uimm5_plus32,
+ uimm5_inssize_plus1, MipsIns>;
+class DINSM_MM64R6_DESC : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64>;
+class DINS_MM64R6_DESC : InsBase<"dins", GPR64Opnd, uimm5, uimm5_inssize_plus1,
+ MipsIns>;
+
//===----------------------------------------------------------------------===//
//
// Instruction Definitions
@@ -116,4 +125,10 @@
ISA_MICROMIPS64R6;
def DMODU_MM64R6 : R6MMR6Rel, DMODU_MM64R6_DESC, DMODU_MM64R6_ENC,
ISA_MICROMIPS64R6;
+ def DINSU_MM64R6: R6MMR6Rel, DINSU_MM64R6_DESC, DINSU_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DINSM_MM64R6: R6MMR6Rel, DINSM_MM64R6_DESC, DINSM_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DINS_MM64R6: R6MMR6Rel, DINS_MM64R6_DESC, DINS_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
}
diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
index 8514d1a..e441e11 100644
--- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td
@@ -847,8 +847,8 @@
// TODO: Add '0 < pos+size <= 32' constraint check to ext instruction
def EXT_MM : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1,
MipsExt>, EXT_FM_MM<0x2c>;
- def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>,
- EXT_FM_MM<0x0c>;
+ def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, uimm5_inssize_plus1,
+ MipsIns>, EXT_FM_MM<0x0c>;
/// Jump Instructions
let DecoderMethod = "DecodeJumpTargetMM" in {
diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td
index 76e2310..d5d794d 100644
--- a/llvm/lib/Target/Mips/Mips64InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td
@@ -277,12 +277,14 @@
EXT_FM<1>;
def DEXTU : ExtBase<"dextu", GPR64Opnd, uimm5_plus32, uimm5_plus1,
MipsExt>, EXT_FM<2>;
+ def DINS : InsBase<"dins", GPR64Opnd, uimm6, uimm5_inssize_plus1, MipsIns>,
+ EXT_FM<7>;
+ def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32, uimm5_inssize_plus1>,
+ EXT_FM<6>;
+ def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5, uimm5_inssize_plus1>,
+ EXT_FM<5>;
}
-def DINS : InsBase<"dins", GPR64Opnd, uimm6, MipsIns>, EXT_FM<7>;
-def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32>, EXT_FM<6>;
-def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5>, EXT_FM<5>;
-
let isCodeGenOnly = 1, rs = 0, shamt = 0 in {
def DSLL64_32 : FR<0x00, 0x3c, (outs GPR64:$rd), (ins GPR32:$rt),
"dsll\t$rd, $rt, 32", [], II_DSLL>;
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td
index 277d2d7f..d120250e 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -403,6 +403,16 @@
let DiagnosticType = "UImm" # Bits # "_" # Offset;
}
+class ConstantUImmRangeAsmOperandClass<int Bottom, int Top,
+ list<AsmOperandClass> Supers = []>
+ : AsmOperandClass {
+ let Name = "ConstantUImmRange" # Bottom # "_" # Top;
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isConstantUImmRange<" # Bottom # ", " # Top # ">";
+ let SuperClasses = Supers;
+ let DiagnosticType = "UImmRange" # Bottom # "_" # Top;
+}
+
class UImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
: AsmOperandClass {
let Name = "UImm" # Bits;
@@ -432,6 +442,8 @@
: ConstantSImmAsmOperandClass<6, [ConstantUImm7AsmOperandClass]>;
def ConstantUImm5Plus1AsmOperandClass
: ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 1>;
+def ConstantUImm5_Range2_64AsmOperandClass
+ : ConstantUImmRangeAsmOperandClass<2, 64, [ConstantUImm6AsmOperandClass]>;
def ConstantUImm5Plus32AsmOperandClass
: ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 32>;
def ConstantUImm5Plus33AsmOperandClass
@@ -542,6 +554,14 @@
let ParserMatchClass = ConstantImmzAsmOperandClass;
}
+// size operand of ins instruction
+def uimm_range_2_64 : Operand<i32> {
+ let PrintMethod = "printUnsignedImm";
+ let EncoderMethod = "getSizeInsEncoding";
+ let DecoderMethod = "DecodeInsSize";
+ let ParserMatchClass = ConstantUImm5_Range2_64AsmOperandClass;
+}
+
// Unsigned Operands
foreach I = {1, 2, 3, 4, 5, 6, 7, 8, 10} in
def uimm # I : Operand<i32> {
@@ -576,6 +596,13 @@
let ParserMatchClass = ConstantUImm5Plus33AsmOperandClass;
}
+def uimm5_inssize_plus1 : Operand<i32> {
+ let PrintMethod = "printUnsignedImm";
+ let ParserMatchClass = ConstantUImm5Plus1AsmOperandClass;
+ let EncoderMethod = "getSizeInsEncoding";
+ let DecoderMethod = "DecodeInsSize";
+}
+
def uimm5_plus32_normalize : Operand<i32> {
let PrintMethod = "printUnsignedImm";
let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass;
@@ -1253,8 +1280,8 @@
FrmR, opstr>, ISA_MIPS32R2;
class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd,
- SDPatternOperator Op = null_frag>:
- InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ins:$size, RO:$src),
+ Operand SizeOpnd, SDPatternOperator Op = null_frag>:
+ InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size, RO:$src),
!strconcat(opstr, " $rt, $rs, $pos, $size"),
[(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size, RO:$src))],
II_INS, FrmR, opstr>, ISA_MIPS32R2 {
@@ -1738,7 +1765,8 @@
// TODO: Add '0 < pos+size <= 32' constraint check to ext instruction
def EXT : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, MipsExt>,
EXT_FM<0>;
-def INS : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, EXT_FM<4>;
+def INS : MMRel, InsBase<"ins", GPR32Opnd, uimm5, uimm5_inssize_plus1, MipsIns>,
+ EXT_FM<4>;
/// Move Control Registers From/To CPU Registers
def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd>, MFC3OP_FM<0x10, 0>, ISA_MIPS32;