summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp73
-rw-r--r--llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp58
-rw-r--r--llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td28
-rw-r--r--llvm/lib/Target/Mips/Mips64InstrInfo.td32
-rw-r--r--llvm/lib/Target/Mips/MipsInstrInfo.td14
5 files changed, 162 insertions, 43 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 0714f8cb522..9bbb430962e 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -465,6 +465,7 @@ public:
Match_NonZeroOperandForSync,
Match_RequiresPosSizeRange0_32,
Match_RequiresPosSizeRange33_64,
+ Match_RequiresPosSizeUImm6,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "MipsGenAsmMatcher.inc"
#undef GET_OPERAND_DIAGNOSTIC_TYPES
@@ -4979,28 +4980,50 @@ 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;
- }
+ 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;
+ }
+ case Mips::DEXT:
+ case Mips::DEXT_MM64R6: {
+ assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
+ "Operands must be immediates for DEXTM!");
+ const signed Pos = Inst.getOperand(2).getImm();
+ const signed Size = Inst.getOperand(3).getImm();
+ if ((1 > (Pos + Size)) || ((Pos + Size) > 63))
+ return Match_RequiresPosSizeUImm6;
+ return Match_Success;
+ }
+ case Mips::DEXTM:
+ case Mips::DEXTU:
+ case Mips::DEXTM_MM64R6:
+ case Mips::DEXTU_MM64R6: {
+ assert(Inst.getOperand(2).isImm() && Inst.getOperand(3).isImm() &&
+ "Operands must be immediates for dextm/dextu!");
+ 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;
@@ -5199,6 +5222,12 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(ErrorStart, "size plus position are not in the range 0 .. 32",
SMRange(ErrorStart, ErrorEnd));
}
+ case Match_RequiresPosSizeUImm6: {
+ SMLoc ErrorStart = Operands[3]->getStartLoc();
+ SMLoc ErrorEnd = Operands[4]->getEndLoc();
+ return Error(ErrorStart, "size plus position are not in the range 1 .. 63",
+ SMRange(ErrorStart, ErrorEnd));
+ }
case Match_RequiresPosSizeRange33_64: {
SMLoc ErrorStart = Operands[3]->getStartLoc();
SMLoc ErrorEnd = Operands[4]->getEndLoc();
diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index 8bd2e791998..ac92fdb6f9e 100644
--- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -523,6 +523,10 @@ template <typename InsnType>
static DecodeStatus DecodeDINS(MCInst &MI, InsnType Insn, uint64_t Address,
const void *Decoder);
+template <typename InsnType>
+static DecodeStatus DecodeDEXT(MCInst &MI, InsnType Insn, uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
@@ -1055,6 +1059,60 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn,
return MCDisassembler::Success;
}
+// Override the generated disassembler to produce DEXT all the time. This is
+// for feature / behaviour parity with binutils.
+template <typename InsnType>
+static DecodeStatus DecodeDEXT(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::DEXT_MM64R6:
+ IsMicroMips = true;
+ LLVM_FALLTHROUGH;
+ case Mips::DEXT:
+ Pos = Lsb;
+ Size = Msbd + 1;
+ break;
+ case Mips::DEXTM_MM64R6:
+ IsMicroMips = true;
+ LLVM_FALLTHROUGH;
+ case Mips::DEXTM:
+ Pos = Lsb;
+ Size = Msbd + 1 + 32;
+ break;
+ case Mips::DEXTU_MM64R6:
+ IsMicroMips = true;
+ LLVM_FALLTHROUGH;
+ case Mips::DEXTU:
+ Pos = Lsb + 32;
+ Size = Msbd + 1;
+ break;
+ default:
+ llvm_unreachable("Unknown DEXT instruction!");
+ }
+
+ MI.setOpcode(IsMicroMips ? Mips::DEXT_MM64R6 : Mips::DEXT);
+
+ // 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.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;
+}
+
// Override the generated disassembler to produce DINS all the time. This is
// for feature / behaviour parity with binutils.
template <typename InsnType>
diff --git a/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
index 4f7248e8d01..e0f4d833392 100644
--- a/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
+++ b/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td
@@ -111,11 +111,8 @@ class EXTBITS_DESC_BASE<string instr_asm, RegisterOperand RO, Operand PosOpnd,
Format Form = FrmR;
string BaseOpcode = instr_asm;
}
-// TODO: Add 'pos + size' constraint check to dext* instructions
-// DEXT: 0 < pos + size <= 63
-// DEXTM, DEXTU: 32 < pos + size <= 64
class DEXT_MMR6_DESC : EXTBITS_DESC_BASE<"dext", GPR64Opnd, uimm5_report_uimm6,
- uimm5_plus1, MipsExt>;
+ uimm5_plus1_report_uimm6, MipsExt>;
class DEXTM_MMR6_DESC : EXTBITS_DESC_BASE<"dextm", GPR64Opnd, uimm5,
uimm5_plus33, MipsExt>;
class DEXTU_MMR6_DESC : EXTBITS_DESC_BASE<"dextu", GPR64Opnd, uimm5_plus32,
@@ -367,12 +364,14 @@ let DecoderNamespace = "MicroMipsR6" in {
def DAHI_MM64R6 : StdMMR6Rel, DAHI_MMR6_DESC, DAHI_MMR6_ENC, ISA_MICROMIPS64R6;
def DATI_MM64R6 : StdMMR6Rel, DATI_MMR6_DESC, DATI_MMR6_ENC, ISA_MICROMIPS64R6;
}
- def DEXT_MM64R6 : StdMMR6Rel, DEXT_MMR6_DESC, DEXT_MMR6_ENC,
- ISA_MICROMIPS64R6;
- def DEXTM_MM64R6 : StdMMR6Rel, DEXTM_MMR6_DESC, DEXTM_MMR6_ENC,
- ISA_MICROMIPS64R6;
- def DEXTU_MM64R6 : StdMMR6Rel, DEXTU_MMR6_DESC, DEXTU_MMR6_ENC,
- ISA_MICROMIPS64R6;
+ let DecoderMethod = "DecodeDEXT" in {
+ def DEXT_MM64R6 : StdMMR6Rel, DEXT_MMR6_DESC, DEXT_MMR6_ENC,
+ ISA_MICROMIPS64R6;
+ def DEXTM_MM64R6 : StdMMR6Rel, DEXTM_MMR6_DESC, DEXTM_MMR6_ENC,
+ ISA_MICROMIPS64R6;
+ def DEXTU_MM64R6 : StdMMR6Rel, DEXTU_MMR6_DESC, DEXTU_MMR6_ENC,
+ ISA_MICROMIPS64R6;
+ }
def DALIGN_MM64R6 : StdMMR6Rel, DALIGN_MMR6_DESC, DALIGN_MMR6_ENC,
ISA_MICROMIPS64R6;
def DDIV_MM64R6 : R6MMR6Rel, DDIV_MM64R6_DESC, DDIV_MM64R6_ENC,
@@ -572,3 +571,12 @@ def : MipsInstAlias<"dins $rt, $rs, $pos, $size",
(DINSU_MM64R6 GPR64Opnd:$rt, GPR64Opnd:$rs,
uimm5_plus32:$pos, uimm5_plus1:$size), 0>,
ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dext $rt, $rs, $pos, $size",
+ (DEXTM_MM64R6 GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5:$pos,
+ uimm5_plus33:$size), 0>,
+ ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dext $rt, $rs, $pos, $size",
+ (DEXTU_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 3f0930355af..04a050c2ff4 100644
--- a/llvm/lib/Target/Mips/Mips64InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td
@@ -317,16 +317,22 @@ let isCodeGenOnly = 1 in
def RDHWR64 : ReadHardware<GPR64Opnd, HWRegsOpnd>, RDHWR_FM;
let AdditionalPredicates = [NotInMicroMips] in {
- // The 'pos + size' constraints are enforced by the code that lowers into
- // MipsISD::Ext.
- def DEXT : ExtBase<"dext", GPR64Opnd, uimm5_report_uimm6, uimm5_plus1,
- immZExt5, immZExt5Plus1, MipsExt>, EXT_FM<3>,
- ISA_MIPS64R2;
- def DEXTM : ExtBase<"dextm", GPR64Opnd, uimm5, uimm5_plus33, immZExt5,
- immZExt5Plus33, MipsExt>, EXT_FM<1>, ISA_MIPS64R2;
- def DEXTU : ExtBase<"dextu", GPR64Opnd, uimm5_plus32, uimm5_plus1,
- immZExt5Plus32, immZExt5Plus1, MipsExt>, EXT_FM<2>,
- ISA_MIPS64R2;
+ // The 'pos + size' constraints for code generation are enforced by the
+ // code that lowers into MipsISD::Ext.
+ // For assembly parsing, we alias dextu and dextm to dext, and match by
+ // operand were possible then check the 'pos + size' in MipsAsmParser.
+ // We override the generated decoder to enforce that dext always comes out
+ // for dextm and dextu like binutils.
+ let DecoderMethod = "DecodeDEXT" in {
+ def DEXT : ExtBase<"dext", GPR64Opnd, uimm5_report_uimm6,
+ uimm5_plus1_report_uimm6, immZExt5, immZExt5Plus1,
+ MipsExt>, EXT_FM<3>, ISA_MIPS64R2;
+ def DEXTM : ExtBase<"dextm", GPR64Opnd, uimm5, uimm5_plus33, immZExt5,
+ immZExt5Plus33, MipsExt>, EXT_FM<1>, ISA_MIPS64R2;
+ def DEXTU : ExtBase<"dextu", GPR64Opnd, uimm5_plus32, uimm5_plus1,
+ immZExt5Plus32, immZExt5Plus1, MipsExt>, EXT_FM<2>,
+ 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
@@ -840,6 +846,12 @@ let AdditionalPredicates = [NotInMicroMips] in {
def : MipsInstAlias<"dins $rt, $rs, $pos, $size",
(DINSU GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5_plus32:$pos,
uimm5_plus1:$size), 0>, ISA_MIPS64R2;
+ def : MipsInstAlias<"dext $rt, $rs, $pos, $size",
+ (DEXTM GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5:$pos,
+ uimm5_plus33:$size), 0>, ISA_MIPS64R2;
+ def : MipsInstAlias<"dext $rt, $rs, $pos, $size",
+ (DEXTU 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 0ff1c4cf145..50515808376 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -690,9 +690,14 @@ def ConstantUImm5Plus32NormalizeAsmOperandClass
// We must also subtract 32 when we render the operand.
let RenderMethod = "addConstantUImmOperands<5, 32, -32>";
}
+def ConstantUImm5Plus1ReportUImm6AsmOperandClass
+ : ConstantUImmAsmOperandClass<
+ 5, [ConstantUImm5Plus32NormalizeAsmOperandClass], 1>{
+ let Name = "ConstantUImm5_Plus1_Report_UImm6";
+}
def ConstantUImm5Plus1AsmOperandClass
: ConstantUImmAsmOperandClass<
- 5, [ConstantUImm5Plus32NormalizeAsmOperandClass], 1>;
+ 5, [ConstantUImm5Plus1ReportUImm6AsmOperandClass], 1>;
def ConstantUImm5AsmOperandClass
: ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus1AsmOperandClass]>;
def ConstantSImm5AsmOperandClass
@@ -799,6 +804,13 @@ def uimm5_plus1 : Operand<i32> {
let ParserMatchClass = ConstantUImm5Plus1AsmOperandClass;
}
+def uimm5_plus1_report_uimm6 : Operand<i32> {
+ let PrintMethod = "printUImm<6, 1>";
+ let EncoderMethod = "getUImmWithOffsetEncoding<5, 1>";
+ let DecoderMethod = "DecodeUImmWithOffset<5, 1>";
+ let ParserMatchClass = ConstantUImm5Plus1ReportUImm6AsmOperandClass;
+}
+
def uimm5_plus32 : Operand<i32> {
let PrintMethod = "printUImm<5, 32>";
let ParserMatchClass = ConstantUImm5Plus32AsmOperandClass;
OpenPOWER on IntegriCloud