summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Dardis <simon.dardis@imgtec.com>2017-09-14 15:17:50 +0000
committerSimon Dardis <simon.dardis@imgtec.com>2017-09-14 15:17:50 +0000
commit6f83ae38a33b06b985597fcbb116c724ec7ca332 (patch)
tree6c5064306d5c84f3e868e72c020f8cf8d2d06c8d
parent18633071a3c4538202d0727c3efbcd8e2521e6ba (diff)
downloadbcm5719-llvm-6f83ae38a33b06b985597fcbb116c724ec7ca332.tar.gz
bcm5719-llvm-6f83ae38a33b06b985597fcbb116c724ec7ca332.zip
[mips] Implement the 'dins' aliases.
Traditionally GAS has provided automatic selection between dins, dinsm and dinsu. Binutils also disassembles all instructions in that family as 'dins' rather than the actual instruction. Reviewers: slthakur Differential Revision: https://reviews.llvm.org/D34877 llvm-svn: 313267
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp36
-rw-r--r--llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp69
-rw-r--r--llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td26
-rw-r--r--llvm/lib/Target/Mips/Mips64InstrInfo.td31
-rw-r--r--llvm/lib/Target/Mips/MipsInstrInfo.td2
-rw-r--r--llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt4
-rw-r--r--llvm/test/MC/Mips/micromips64r6/invalid-wrong-error.s1
-rw-r--r--llvm/test/MC/Mips/micromips64r6/invalid.s2
-rw-r--r--llvm/test/MC/Mips/micromips64r6/valid.s2
-rw-r--r--llvm/test/MC/Mips/mips64extins.s30
10 files changed, 165 insertions, 38 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 9fcf917a853..0714f8cb522 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -463,6 +463,8 @@ public:
Match_RequiresSameSrcAndDst,
Match_NoFCCRegisterForCurrentISA,
Match_NonZeroOperandForSync,
+ Match_RequiresPosSizeRange0_32,
+ Match_RequiresPosSizeRange33_64,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "MipsGenAsmMatcher.inc"
#undef GET_OPERAND_DIAGNOSTIC_TYPES
@@ -4977,6 +4979,28 @@ unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
return Match_RequiresDifferentOperands;
return Match_Success;
+ case Mips::DINS:
+ case Mips::DINS_MM64R6: {
+ assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
+ "Operands must be immediates for dins!");
+ const signed Pos = Inst.getOperand(2).getImm();
+ const signed Size = Inst.getOperand(3).getImm();
+ if ((0 > (Pos + Size)) || ((Pos + Size) > 32))
+ return Match_RequiresPosSizeRange0_32;
+ return Match_Success;
+ }
+ case Mips::DINSM:
+ case Mips::DINSM_MM64R6:
+ case Mips::DINSU:
+ case Mips::DINSU_MM64R6: {
+ assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
+ "Operands must be immediates for dinsm/dinsu!");
+ const signed Pos = Inst.getOperand(2).getImm();
+ const signed Size = Inst.getOperand(3).getImm();
+ if ((32 >= (Pos + Size)) || ((Pos + Size) > 64))
+ return Match_RequiresPosSizeRange33_64;
+ return Match_Success;
+ }
}
uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
@@ -5169,6 +5193,18 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_MemSImm16:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected memory with 16-bit signed offset");
+ case Match_RequiresPosSizeRange0_32: {
+ SMLoc ErrorStart = Operands[3]->getStartLoc();
+ SMLoc ErrorEnd = Operands[4]->getEndLoc();
+ return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
+ SMRange(ErrorStart, ErrorEnd));
+ }
+ case Match_RequiresPosSizeRange33_64: {
+ SMLoc ErrorStart = Operands[3]->getStartLoc();
+ SMLoc ErrorEnd = Operands[4]->getEndLoc();
+ return Error(ErrorStart, "size plus position are not in the range 33 .. 64",
+ SMRange(ErrorStart, ErrorEnd));
+ }
}
llvm_unreachable("Implement any new match types added!");
diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index 41b965731e3..8bd2e791998 100644
--- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -519,6 +519,10 @@ static DecodeStatus
DecodeBlezGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
+template <typename InsnType>
+static DecodeStatus DecodeDINS(MCInst &MI, InsnType Insn, uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
@@ -1051,6 +1055,60 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn,
return MCDisassembler::Success;
}
+// Override the generated disassembler to produce DINS all the time. This is
+// for feature / behaviour parity with binutils.
+template <typename InsnType>
+static DecodeStatus DecodeDINS(MCInst &MI, InsnType Insn, uint64_t Address,
+ const void *Decoder) {
+ unsigned Msbd = fieldFromInstruction(Insn, 11, 5);
+ unsigned Lsb = fieldFromInstruction(Insn, 6, 5);
+ unsigned Size = 0;
+ unsigned Pos = 0;
+ bool IsMicroMips = false;
+
+ switch (MI.getOpcode()) {
+ case Mips::DINS_MM64R6:
+ IsMicroMips = true;
+ LLVM_FALLTHROUGH;
+ case Mips::DINS:
+ Pos = Lsb;
+ Size = Msbd + 1 - Pos;
+ break;
+ case Mips::DINSM_MM64R6:
+ IsMicroMips = true;
+ LLVM_FALLTHROUGH;
+ case Mips::DINSM:
+ Pos = Lsb;
+ Size = Msbd + 33 - Pos;
+ break;
+ case Mips::DINSU_MM64R6:
+ IsMicroMips = true;
+ LLVM_FALLTHROUGH;
+ case Mips::DINSU:
+ Pos = Lsb + 32;
+ // mbsd = pos + size - 33
+ // mbsd - pos + 33 = size
+ Size = Msbd + 33 - Pos;
+ break;
+ default:
+ llvm_unreachable("Unknown DINS instruction!");
+ }
+
+ // Although the format of the instruction is similar, rs and rt are swapped
+ // for microMIPS64R6.
+ InsnType Rs = fieldFromInstruction(Insn, 21, 5);
+ InsnType Rt = fieldFromInstruction(Insn, 16, 5);
+ if (IsMicroMips)
+ std::swap(Rs, Rt);
+
+ MI.setOpcode(IsMicroMips ? Mips::DINS_MM64R6 : Mips::DINS);
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rt)));
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rs)));
+ MI.addOperand(MCOperand::createImm(Pos));
+ MI.addOperand(MCOperand::createImm(Size));
+
+ return MCDisassembler::Success;
+}
/// Read two bytes from the ArrayRef and return 16 bit halfword sorted
/// according to the given endianness.
static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
@@ -2260,15 +2318,10 @@ static DecodeStatus DecodeInsSize(MCInst &Inst,
uint64_t Address,
const void *Decoder) {
// First we need to grab the pos(lsb) from MCInst.
+ // This function only handles the 32 bit variants of ins, as dins
+ // variants are handled differently.
int Pos = Inst.getOperand(2).getImm();
- if (Inst.getOpcode() == Mips::DINSU)
- Pos += 32;
- int Size;
- if (Inst.getOpcode() == Mips::DINSM ||
- Inst.getOpcode() == Mips::DINSU)
- Size = (int) Insn - Pos + 33;
- else
- Size = (int) Insn - Pos + 1;
+ int Size = (int) Insn - Pos + 1;
Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Size)));
return MCDisassembler::Success;
}
diff --git a/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
index a37b31643ac..4f7248e8d01 100644
--- a/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
@@ -168,8 +168,9 @@ class DINSU_MM64R6_DESC : InsBase<"dinsu", GPR64Opnd, uimm5_plus32,
immZExt5Plus1, MipsIns>;
class DINSM_MM64R6_DESC : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64,
immZExt5, immZExtRange2To64, MipsIns>;
-class DINS_MM64R6_DESC : InsBase<"dins", GPR64Opnd, uimm5, uimm5_inssize_plus1,
- immZExt5, immZExt5Plus1, MipsIns>;
+class DINS_MM64R6_DESC : InsBase<"dins", GPR64Opnd, uimm5_report_uimm6,
+ uimm5_inssize_plus1, immZExt5, immZExt5Plus1,
+ MipsIns>;
class DMTC0_MM64R6_DESC : MTC0_MMR6_DESC_BASE<"dmtc0", COP0Opnd, GPR64Opnd,
II_DMTC0>;
class DMTC1_MM64R6_DESC : MTC1_MMR6_DESC_BASE<"dmtc1", FGR64Opnd, GPR64Opnd,
@@ -382,12 +383,14 @@ let DecoderNamespace = "MicroMipsR6" in {
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;
+ let DecoderMethod = "DecodeDINS" in {
+ 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;
+ }
def DMTC0_MM64R6 : StdMMR6Rel, DMTC0_MM64R6_ENC, DMTC0_MM64R6_DESC,
ISA_MICROMIPS64R6;
def DMTC1_MM64R6 : StdMMR6Rel, DMTC1_MM64R6_DESC, DMTC1_MM64R6_ENC,
@@ -562,3 +565,10 @@ def : MipsInstAlias<"dsrl $rd, $rt",
def : MipsInstAlias<"dsll $rd, $rt",
(DSLLV_MM64R6 GPR64Opnd:$rd, GPR64Opnd:$rd,
GPR32Opnd:$rt), 0>, ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dins $rt, $rs, $pos, $size",
+ (DINSM_MM64R6 GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5:$pos,
+ uimm_range_2_64:$size), 0>, ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dins $rt, $rs, $pos, $size",
+ (DINSU_MM64R6 GPR64Opnd:$rt, GPR64Opnd:$rs,
+ uimm5_plus32:$pos, uimm5_plus1:$size), 0>,
+ ISA_MICROMIPS64R6;
diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td
index a5c3096739c..3f0930355af 100644
--- a/llvm/lib/Target/Mips/Mips64InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td
@@ -327,14 +327,23 @@ let AdditionalPredicates = [NotInMicroMips] in {
def DEXTU : ExtBase<"dextu", GPR64Opnd, uimm5_plus32, uimm5_plus1,
immZExt5Plus32, immZExt5Plus1, MipsExt>, EXT_FM<2>,
ISA_MIPS64R2;
- def DINS : InsBase<"dins", GPR64Opnd, uimm6, uimm5_inssize_plus1, immZExt5,
- immZExt5Plus1, MipsIns>, EXT_FM<7>, ISA_MIPS64R2;
- def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32, uimm5_inssize_plus1,
- immZExt5Plus32, immZExt5Plus1, MipsIns>,
- EXT_FM<6>, ISA_MIPS64R2;
- def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64,
- immZExt5, immZExtRange2To64, MipsIns>,
- EXT_FM<5>, ISA_MIPS64R2;
+ // The 'pos + size' constraints for code generation are enforced by the
+ // code that lowers into MipsISD::Ins.
+ // For assembly parsing, we alias dinsu and dinsm to dins, and match by
+ // operand were possible then check the 'pos + size' in MipsAsmParser.
+ // We override the generated decoder to enforce that dins always comes out
+ // for dinsm and dinsu like binutils.
+ let DecoderMethod = "DecodeDINS" in {
+ def DINS : InsBase<"dins", GPR64Opnd, uimm6, uimm5_inssize_plus1,
+ immZExt5, immZExt5Plus1, MipsIns>, EXT_FM<7>,
+ ISA_MIPS64R2;
+ def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32, uimm5_inssize_plus1,
+ immZExt5Plus32, immZExt5Plus1, MipsIns>,
+ EXT_FM<6>, ISA_MIPS64R2;
+ def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64,
+ immZExt5, immZExtRange2To64, MipsIns>,
+ EXT_FM<5>, ISA_MIPS64R2;
+ }
}
let isCodeGenOnly = 1, AdditionalPredicates = [NotInMicroMips] in {
@@ -825,6 +834,12 @@ let AdditionalPredicates = [NotInMicroMips] in {
def : MipsInstAlias<"dsll $rd, $rt",
(DSLLV GPR64Opnd:$rd, GPR64Opnd:$rd, GPR32Opnd:$rt), 0>,
ISA_MIPS3;
+ def : MipsInstAlias<"dins $rt, $rs, $pos, $size",
+ (DINSM GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5:$pos,
+ uimm_range_2_64:$size), 0>, ISA_MIPS64R2;
+ def : MipsInstAlias<"dins $rt, $rs, $pos, $size",
+ (DINSU GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5_plus32:$pos,
+ uimm5_plus1:$size), 0>, ISA_MIPS64R2;
// Two operand (implicit 0 selector) versions:
def : MipsInstAlias<"dmtc0 $rt, $rd",
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td
index 22410864d70..0ff1c4cf145 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -883,7 +883,7 @@ def uimm16_altrelaxed : Operand<i32> {
// Like uimm5 but reports a less confusing error for 32-63 when
// an instruction alias permits that.
def uimm5_report_uimm6 : Operand<i32> {
- let PrintMethod = "printUImm<5>";
+ let PrintMethod = "printUImm<6>";
let ParserMatchClass = ConstantUImm5ReportUImm6AsmOperandClass;
}
diff --git a/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt b/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt
index 337be2fac4f..66827e6d920 100644
--- a/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt
+++ b/llvm/test/MC/Disassembler/Mips/micromips64r6/valid.txt
@@ -189,8 +189,8 @@
0x00 0x00 0x39 0x7c # CHECK: evp $zero
0x00 0x00 0x43 0x7c # CHECK: tlbinv
0x00 0x00 0x53 0x7c # CHECK: tlbinvf
-0x58 0x82 0x20 0x34 # CHECK: dinsu $4, $2, 32, 5
-0x58 0x82 0x38 0xc4 # CHECK: dinsm $4, $2, 3, 5
+0x58 0x82 0x20 0x34 # CHECK: dins $4, $2, 32, 5
+0x58 0x82 0x48 0xc4 # CHECK: dins $4, $2, 3, 39
0x58 0x82 0x38 0xcc # CHECK: dins $4, $2, 3, 5
0x00 0xa9 0x02 0xfc # CHECK: mtc0 $5, $9, 0
0x00 0xa9 0x02 0xfc # CHECK: mtc0 $5, $9
diff --git a/llvm/test/MC/Mips/micromips64r6/invalid-wrong-error.s b/llvm/test/MC/Mips/micromips64r6/invalid-wrong-error.s
index 977a2d031f2..7afa97c997d 100644
--- a/llvm/test/MC/Mips/micromips64r6/invalid-wrong-error.s
+++ b/llvm/test/MC/Mips/micromips64r6/invalid-wrong-error.s
@@ -34,7 +34,6 @@
tne $8, $9, -1 # CHECK: :[[@LINE]]:15: error: expected 10-bit unsigned immediate
tne $8, $9, 16 # CHECK: :[[@LINE]]:3: error: instruction requires a CPU feature not currently enabled
dins $2, $3, -1, 1 # CHECK: :[[@LINE]]:16: error: expected 6-bit unsigned immediate
- dins $2, $3, 32, 1 # CHECK: :[[@LINE]]:3: error: instruction requires a CPU feature not currently enabled
syscall -1 # CHECK: :[[@LINE]]:11: error: expected 20-bit unsigned immediate
syscall $4 # CHECK: :[[@LINE]]:11: error: expected 20-bit unsigned immediate
syscall 1024 # CHECK: :[[@LINE]]:3: error: instruction requires a CPU feature not currently enabled
diff --git a/llvm/test/MC/Mips/micromips64r6/invalid.s b/llvm/test/MC/Mips/micromips64r6/invalid.s
index 30021ea10f0..ffe50e75bf4 100644
--- a/llvm/test/MC/Mips/micromips64r6/invalid.s
+++ b/llvm/test/MC/Mips/micromips64r6/invalid.s
@@ -45,9 +45,7 @@
dextu $2, $3, 64, 1 # CHECK: :[[@LINE]]:17: error: expected immediate in range 32 .. 63
dextu $2, $3, 32, 0 # CHECK: :[[@LINE]]:21: error: expected immediate in range 1 .. 32
dextu $2, $3, 32, 33 # CHECK: :[[@LINE]]:21: error: expected immediate in range 1 .. 32
- dins $2, $3, 31, 33 # CHECK: :[[@LINE]]:20: error: expected immediate in range 1 .. 32
dins $2, $3, 31, 0 # CHECK: :[[@LINE]]:20: error: expected immediate in range 1 .. 32
- # FIXME: Check '32 <= pos + size <= 64' constraint on dinsm
dinsm $2, $3, -1, 1 # CHECK: :[[@LINE]]:17: error: expected 5-bit unsigned immediate
dinsm $2, $3, 32, 1 # CHECK: :[[@LINE]]:17: error: expected 5-bit unsigned immediate
dinsm $2, $3, 31, 0 # CHECK: :[[@LINE]]:21: error: expected immediate in range 2 .. 64
diff --git a/llvm/test/MC/Mips/micromips64r6/valid.s b/llvm/test/MC/Mips/micromips64r6/valid.s
index 3ead62fc616..641e16c1457 100644
--- a/llvm/test/MC/Mips/micromips64r6/valid.s
+++ b/llvm/test/MC/Mips/micromips64r6/valid.s
@@ -198,7 +198,7 @@ a:
tlbinv # CHECK: tlbinv # encoding: [0x00,0x00,0x43,0x7c]
tlbinvf # CHECK: tlbinvf # encoding: [0x00,0x00,0x53,0x7c]
dinsu $4, $2, 32, 5 # CHECK: dinsu $4, $2, 32, 5 # encoding: [0x58,0x82,0x20,0x34]
- dinsm $4, $2, 3, 5 # CHECK: dinsm $4, $2, 3, 5 # encoding: [0x58,0x82,0x38,0xc4]
+ dinsm $4, $2, 31, 5 # CHECK: dinsm $4, $2, 31, 5 # encoding: [0x58,0x82,0x1f,0xc4]
dins $4, $2, 3, 5 # CHECK: dins $4, $2, 3, 5 # encoding: [0x58,0x82,0x38,0xcc]
lh $2, 8($4) # CHECK: lh $2, 8($4) # encoding: [0x3c,0x44,0x00,0x08]
lhe $4, 8($2) # CHECK: lhe $4, 8($2) # encoding: [0x60,0x82,0x6a,0x08]
diff --git a/llvm/test/MC/Mips/mips64extins.s b/llvm/test/MC/Mips/mips64extins.s
index 5bd18ff62d5..ec8281b1ebf 100644
--- a/llvm/test/MC/Mips/mips64extins.s
+++ b/llvm/test/MC/Mips/mips64extins.s
@@ -1,9 +1,25 @@
# RUN: llvm-mc -arch=mips64el -filetype=obj -mcpu=mips64r2 -target-abi=n64 %s -o - \
-# RUN: | llvm-objdump -disassemble - | FileCheck %s
+# RUN: | llvm-objdump -disassemble - | FileCheck --check-prefix=OBJ %s
+# RUN: llvm-mc -arch=mips64el -filetype=obj -mcpu=mips64r6 -mattr=+micromips \
+# RUN: -target-abi=n64 %s -o - | llvm-objdump -disassemble - \
+# RUN: | FileCheck --check-prefix=OBJ %s
- dext $2, $4, 5, 10 # CHECK: dext ${{[0-9]+}}, ${{[0-9]+}}, 5, 10
- dextu $2, $4, 34, 6 # CHECK: dextu ${{[0-9]+}}, ${{[0-9]+}}, 34, 6
- dextm $2, $4, 5, 34 # CHECK: dextm ${{[0-9]+}}, ${{[0-9]+}}, 5, 34
- dins $4, $5, 8, 10 # CHECK: dins ${{[0-9]+}}, ${{[0-9]+}}, 8, 10
- dinsm $4, $5, 30, 6 # CHECK: dinsm ${{[0-9]+}}, ${{[0-9]+}}, 30, 6
- dinsu $4, $5, 40, 13 # CHECK: dinsu ${{[0-9]+}}, ${{[0-9]+}}, 40, 13
+# RUN: llvm-mc -arch=mips64el -mcpu=mips64r2 -target-abi=n64 %s -o - \
+# RUN: | FileCheck --check-prefix=ASM %s
+# RUN: llvm-mc -arch=mips64el -mcpu=mips64r6 -mattr=+micromips -target-abi=n64 \
+# RUN: %s -o - | FileCheck --check-prefix=ASM %s
+
+ dext $2, $4, 5, 10 # OBJ: dext ${{[0-9]+}}, ${{[0-9]+}}, 5, 10
+ dextu $2, $4, 34, 6 # OBJ: dextu ${{[0-9]+}}, ${{[0-9]+}}, 34, 6
+ dextm $2, $4, 5, 34 # OBJ: dextm ${{[0-9]+}}, ${{[0-9]+}}, 5, 34
+ dins $4, $5, 8, 10 # OBJ: dins ${{[0-9]+}}, ${{[0-9]+}}, 8, 10
+ dinsm $4, $5, 30, 6 # OBJ: dins ${{[0-9]+}}, ${{[0-9]+}}, 30, 6
+ dinsu $4, $5, 40, 13 # OBJ: dins ${{[0-9]+}}, ${{[0-9]+}}, 40, 13
+ # check the aliases
+ dins $2, $4, 5, 10 # OBJ: dins ${{[0-9]+}}, ${{[0-9]+}}, 5, 10
+ dins $2, $4, 34, 6 # OBJ: dins ${{[0-9]+}}, ${{[0-9]+}}, 34, 6
+ dins $2, $4, 5, 34 # OBJ: dins ${{[0-9]+}}, ${{[0-9]+}}, 5, 34
+ # check the edge values
+ dins $3, $4, 31, 1 # ASM: dins $3, $4, 31, 1
+ dins $3, $4, 31, 33 # ASM: dinsm $3, $4, 31, 33
+ dins $3, $4, 32, 32 # ASM: dinsu $3, $4, 32, 32
OpenPOWER on IntegriCloud