aboutsummaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-02-01 21:34:47 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-02-01 21:34:47 +0000
commit823f87a1f80708ce9ba318cc0b07632e76b74d43 (patch)
tree400cc7e5d4548d5f3829f7feea7f7942b4e62dd4 /lib/Target
parentaac4ca60bc813a35242145a1f92f325303d5df6e (diff)
downloadsrc-823f87a1f80708ce9ba318cc0b07632e76b74d43.tar.gz
src-823f87a1f80708ce9ba318cc0b07632e76b74d43.zip
Notes
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp17
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h4
-rw-r--r--lib/Target/Mips/MicroMipsInstrFPU.td107
-rw-r--r--lib/Target/Mips/MicroMipsInstrFormats.td7
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp16
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.h1
-rw-r--r--lib/Target/Mips/MipsFastISel.cpp4
-rw-r--r--lib/Target/Mips/MipsInstrFPU.td211
-rw-r--r--lib/Target/Mips/MipsInstrFormats.td8
-rw-r--r--lib/Target/Mips/MipsTargetObjectFile.cpp8
-rw-r--r--lib/Target/Mips/MipsTargetObjectFile.h2
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td13
-rw-r--r--lib/Target/PowerPC/PPCSchedule.td2
-rw-r--r--lib/Target/PowerPC/PPCScheduleE500mc.td8
-rw-r--r--lib/Target/PowerPC/PPCScheduleE5500.td10
15 files changed, 371 insertions, 47 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 97ca11ca501e..d054578deb67 100644
--- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -413,6 +413,7 @@ public:
Match_RequiresDifferentOperands,
Match_RequiresNoZeroRegister,
Match_RequiresSameSrcAndDst,
+ Match_NoFCCRegisterForCurrentISA,
Match_NonZeroOperandForSync,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "MipsGenAsmMatcher.inc"
@@ -1461,8 +1462,6 @@ public:
bool isFCCAsmReg() const {
if (!(isRegIdx() && RegIdx.Kind & RegKind_FCC))
return false;
- if (!AsmParser.hasEightFccRegisters())
- return RegIdx.Index == 0;
return RegIdx.Index <= 7;
}
bool isACCAsmReg() const {
@@ -4053,6 +4052,7 @@ MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
return Match_RequiresSameSrcAndDst;
}
}
+
unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
switch (Inst.getOpcode()) {
// As described by the MIPSR6 spec, daui must not use the zero operand for
@@ -4131,9 +4131,15 @@ unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
return Match_RequiresDifferentOperands;
return Match_Success;
- default:
- return Match_Success;
}
+
+ uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags;
+ if ((TSFlags & MipsII::HasFCCRegOperand) &&
+ (Inst.getOperand(0).getReg() != Mips::FCC0) && !hasEightFccRegisters())
+ return Match_NoFCCRegisterForCurrentISA;
+
+ return Match_Success;
+
}
static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
@@ -4191,6 +4197,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(IDLoc, "invalid operand ($zero) for instruction");
case Match_RequiresSameSrcAndDst:
return Error(IDLoc, "source and destination must match");
+ case Match_NoFCCRegisterForCurrentISA:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "non-zero fcc register doesn't exist in current ISA level");
case Match_Immz:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
case Match_UImm1_0:
diff --git a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
index 35de7b27bf10..a90db2384c46 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
@@ -123,7 +123,9 @@ namespace MipsII {
HasForbiddenSlot = 1 << 5,
/// IsPCRelativeLoad - A Load instruction with implicit source register
/// ($pc) with explicit offset and destination register
- IsPCRelativeLoad = 1 << 6
+ IsPCRelativeLoad = 1 << 6,
+ /// HasFCCRegOperand - Instruction uses an $fcc<x> register.
+ HasFCCRegOperand = 1 << 7
};
}
diff --git a/lib/Target/Mips/MicroMipsInstrFPU.td b/lib/Target/Mips/MicroMipsInstrFPU.td
index fc83761e409b..5600f71ff68e 100644
--- a/lib/Target/Mips/MicroMipsInstrFPU.td
+++ b/lib/Target/Mips/MicroMipsInstrFPU.td
@@ -27,9 +27,20 @@ def SUXC1_MM : MMRel, SWXC1_FT<"suxc1", AFGR64Opnd, II_SUXC1>,
SWXC1_FM_MM<0x188>, INSN_MIPS5_32R2_NOT_32R6_64R6;
def FCMP_S32_MM : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>,
- CEQS_FM_MM<0>;
+ CEQS_FM_MM<0> {
+ // FIXME: This is a required to work around the fact that these instructions
+ // only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the
+ // fcc register set is used directly.
+ bits<3> fcc = 0;
+}
+
def FCMP_D32_MM : MMRel, CEQS_FT<"d", AFGR64, II_C_CC_D, MipsFPCmp>,
- CEQS_FM_MM<1>;
+ CEQS_FM_MM<1> {
+ // FIXME: This is a required to work around the fact that these instructions
+ // only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the
+ // fcc register set is used directly.
+ bits<3> fcc = 0;
+}
def BC1F_MM : MMRel, BC1F_FT<"bc1f", brtarget_mm, II_BC1F, MIPS_BRANCH_F>,
BC1F_FM_MM<0x1c>, ISA_MIPS1_NOT_32R6_64R6;
@@ -164,6 +175,98 @@ let AdditionalPredicates = [InMicroMips] in {
def SWC1_MM : MMRel, SW_FT<"swc1", FGR32Opnd, mem_mm_16, II_SWC1, store>,
LW_FM_MM<0x26>;
}
+
+ multiclass C_COND_MM<string TypeStr, RegisterOperand RC, bits<2> fmt,
+ InstrItinClass itin> {
+ def C_F_#NAME#_MM : MMRel, C_COND_FT<"f", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 0> {
+ let BaseOpcode = "c.f."#NAME;
+ let isCommutable = 1;
+ }
+ def C_UN_#NAME#_MM : MMRel, C_COND_FT<"un", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 1> {
+ let BaseOpcode = "c.un."#NAME;
+ let isCommutable = 1;
+ }
+ def C_EQ_#NAME#_MM : MMRel, C_COND_FT<"eq", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 2> {
+ let BaseOpcode = "c.eq."#NAME;
+ let isCommutable = 1;
+ }
+ def C_UEQ_#NAME#_MM : MMRel, C_COND_FT<"ueq", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 3> {
+ let BaseOpcode = "c.ueq."#NAME;
+ let isCommutable = 1;
+ }
+ def C_OLT_#NAME#_MM : MMRel, C_COND_FT<"olt", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 4> {
+ let BaseOpcode = "c.olt."#NAME;
+ }
+ def C_ULT_#NAME#_MM : MMRel, C_COND_FT<"ult", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 5> {
+ let BaseOpcode = "c.ult."#NAME;
+ }
+ def C_OLE_#NAME#_MM : MMRel, C_COND_FT<"ole", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 6> {
+ let BaseOpcode = "c.ole."#NAME;
+ }
+ def C_ULE_#NAME#_MM : MMRel, C_COND_FT<"ule", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 7> {
+ let BaseOpcode = "c.ule."#NAME;
+ }
+ def C_SF_#NAME#_MM : MMRel, C_COND_FT<"sf", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 8> {
+ let BaseOpcode = "c.sf."#NAME;
+ let isCommutable = 1;
+ }
+ def C_NGLE_#NAME#_MM : MMRel, C_COND_FT<"ngle", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 9> {
+ let BaseOpcode = "c.ngle."#NAME;
+ }
+ def C_SEQ_#NAME#_MM : MMRel, C_COND_FT<"seq", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 10> {
+ let BaseOpcode = "c.seq."#NAME;
+ let isCommutable = 1;
+ }
+ def C_NGL_#NAME#_MM : MMRel, C_COND_FT<"ngl", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 11> {
+ let BaseOpcode = "c.ngl."#NAME;
+ }
+ def C_LT_#NAME#_MM : MMRel, C_COND_FT<"lt", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 12> {
+ let BaseOpcode = "c.lt."#NAME;
+ }
+ def C_NGE_#NAME#_MM : MMRel, C_COND_FT<"nge", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 13> {
+ let BaseOpcode = "c.nge."#NAME;
+ }
+ def C_LE_#NAME#_MM : MMRel, C_COND_FT<"le", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 14> {
+ let BaseOpcode = "c.le."#NAME;
+ }
+ def C_NGT_#NAME#_MM : MMRel, C_COND_FT<"ngt", TypeStr, RC, itin>,
+ C_COND_FM_MM<fmt, 15> {
+ let BaseOpcode = "c.ngt."#NAME;
+ }
+ }
+
+ defm S : C_COND_MM<"s", FGR32Opnd, 0b00, II_C_CC_S>,
+ ISA_MIPS1_NOT_32R6_64R6;
+ defm D32 : C_COND_MM<"d", AFGR64Opnd, 0b01, II_C_CC_D>,
+ ISA_MIPS1_NOT_32R6_64R6, FGR_32;
+ let DecoderNamespace = "Mips64" in
+ defm D64 : C_COND_MM<"d", FGR64Opnd, 0b01, II_C_CC_D>,
+ ISA_MIPS1_NOT_32R6_64R6, FGR_64;
+
+ defm S_MM : C_COND_ALIASES<"s", FGR32Opnd>, HARDFLOAT,
+ ISA_MIPS1_NOT_32R6_64R6;
+ defm D32_MM : C_COND_ALIASES<"d", AFGR64Opnd>, HARDFLOAT,
+ ISA_MIPS1_NOT_32R6_64R6, FGR_32;
+ defm D64_MM : C_COND_ALIASES<"d", FGR64Opnd>, HARDFLOAT,
+ ISA_MIPS1_NOT_32R6_64R6, FGR_64;
+
+ defm : BC1_ALIASES<BC1T_MM, "bc1t", BC1F_MM, "bc1f">,
+ ISA_MIPS1_NOT_32R6_64R6, HARDFLOAT;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/Mips/MicroMipsInstrFormats.td b/lib/Target/Mips/MicroMipsInstrFormats.td
index 8b595f9e6c4c..774976828a0c 100644
--- a/lib/Target/Mips/MicroMipsInstrFormats.td
+++ b/lib/Target/Mips/MicroMipsInstrFormats.td
@@ -766,6 +766,7 @@ class SWXC1_FM_MM<bits<9> funct> : MMArch {
class CEQS_FM_MM<bits<2> fmt> : MMArch {
bits<5> fs;
bits<5> ft;
+ bits<3> fcc;
bits<4> cond;
bits<32> Inst;
@@ -773,13 +774,17 @@ class CEQS_FM_MM<bits<2> fmt> : MMArch {
let Inst{31-26} = 0x15;
let Inst{25-21} = ft;
let Inst{20-16} = fs;
- let Inst{15-13} = 0x0; // cc
+ let Inst{15-13} = fcc;
let Inst{12} = 0;
let Inst{11-10} = fmt;
let Inst{9-6} = cond;
let Inst{5-0} = 0x3c;
}
+class C_COND_FM_MM<bits <2> fmt, bits<4> c> : CEQS_FM_MM<fmt> {
+ let cond = c;
+}
+
class BC1F_FM_MM<bits<5> tf> : MMArch {
bits<16> offset;
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
index 179695bc6988..04d6529a073d 100644
--- a/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -1037,6 +1037,22 @@ void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
// TODO: implement
}
+// Emit .dtprelword or .dtpreldword directive
+// and value for debug thread local expression.
+void MipsAsmPrinter::EmitDebugValue(const MCExpr *Value,
+ unsigned Size) const {
+ switch (Size) {
+ case 4:
+ OutStreamer->EmitDTPRel32Value(Value);
+ break;
+ case 8:
+ OutStreamer->EmitDTPRel64Value(Value);
+ break;
+ default:
+ llvm_unreachable("Unexpected size of expression value.");
+ }
+}
+
// Align all targets of indirect branches on bundle size. Used only if target
// is NaCl.
void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) {
diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h
index 259e557e1283..c5cf5241c236 100644
--- a/lib/Target/Mips/MipsAsmPrinter.h
+++ b/lib/Target/Mips/MipsAsmPrinter.h
@@ -140,6 +140,7 @@ public:
void EmitStartOfAsmFile(Module &M) override;
void EmitEndOfAsmFile(Module &M) override;
void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
+ void EmitDebugValue(const MCExpr *Value, unsigned Size) const override;
};
}
diff --git a/lib/Target/Mips/MipsFastISel.cpp b/lib/Target/Mips/MipsFastISel.cpp
index 29f3e2c07e04..a44192f57aa0 100644
--- a/lib/Target/Mips/MipsFastISel.cpp
+++ b/lib/Target/Mips/MipsFastISel.cpp
@@ -698,8 +698,8 @@ bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) {
unsigned RegWithOne = createResultReg(&Mips::GPR32RegClass);
emitInst(Mips::ADDiu, RegWithZero).addReg(Mips::ZERO).addImm(0);
emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1);
- emitInst(Opc).addReg(LeftReg).addReg(RightReg).addReg(
- Mips::FCC0, RegState::ImplicitDefine);
+ emitInst(Opc).addReg(Mips::FCC0, RegState::Define).addReg(LeftReg)
+ .addReg(RightReg);
emitInst(CondMovOpc, ResultReg)
.addReg(RegWithOne)
.addReg(Mips::FCC0)
diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td
index ab7aa9dcdcae..df42d56d041b 100644
--- a/lib/Target/Mips/MipsInstrFPU.td
+++ b/lib/Target/Mips/MipsInstrFPU.td
@@ -219,6 +219,7 @@ class BC1F_FT<string opstr, DAGOperand opnd, InstrItinClass Itin,
let isTerminator = 1;
let hasDelaySlot = DelaySlot;
let Defs = [AT];
+ let hasFCCRegOperand = 1;
}
class CEQS_FT<string typestr, RegisterClass RC, InstrItinClass Itin,
@@ -229,41 +230,106 @@ class CEQS_FT<string typestr, RegisterClass RC, InstrItinClass Itin,
!strconcat("c.$cond.", typestr)>, HARDFLOAT {
let Defs = [FCC0];
let isCodeGenOnly = 1;
+ let hasFCCRegOperand = 1;
}
+
+// Note: MIPS-IV introduced $fcc1-$fcc7 and renamed FCSR31[23] $fcc0. Rather
+// duplicating the instruction definition for MIPS1 - MIPS3, we expand
+// c.cond.ft if necessary, and reject it after constructing the
+// instruction if the ISA doesn't support it.
class C_COND_FT<string CondStr, string Typestr, RegisterOperand RC,
InstrItinClass itin> :
- InstSE<(outs), (ins RC:$fs, RC:$ft),
- !strconcat("c.", CondStr, ".", Typestr, "\t$fs, $ft"), [], itin,
- FrmFR>, HARDFLOAT;
+ InstSE<(outs FCCRegsOpnd:$fcc), (ins RC:$fs, RC:$ft),
+ !strconcat("c.", CondStr, ".", Typestr, "\t$fcc, $fs, $ft"), [], itin,
+ FrmFR>, HARDFLOAT {
+ let isCompare = 1;
+ let hasFCCRegOperand = 1;
+}
+
multiclass C_COND_M<string TypeStr, RegisterOperand RC, bits<5> fmt,
InstrItinClass itin> {
- def C_F_#NAME : C_COND_FT<"f", TypeStr, RC, itin>, C_COND_FM<fmt, 0>;
- def C_UN_#NAME : C_COND_FT<"un", TypeStr, RC, itin>, C_COND_FM<fmt, 1>;
- def C_EQ_#NAME : C_COND_FT<"eq", TypeStr, RC, itin>, C_COND_FM<fmt, 2>;
- def C_UEQ_#NAME : C_COND_FT<"ueq", TypeStr, RC, itin>, C_COND_FM<fmt, 3>;
- def C_OLT_#NAME : C_COND_FT<"olt", TypeStr, RC, itin>, C_COND_FM<fmt, 4>;
- def C_ULT_#NAME : C_COND_FT<"ult", TypeStr, RC, itin>, C_COND_FM<fmt, 5>;
- def C_OLE_#NAME : C_COND_FT<"ole", TypeStr, RC, itin>, C_COND_FM<fmt, 6>;
- def C_ULE_#NAME : C_COND_FT<"ule", TypeStr, RC, itin>, C_COND_FM<fmt, 7>;
- def C_SF_#NAME : C_COND_FT<"sf", TypeStr, RC, itin>, C_COND_FM<fmt, 8>;
- def C_NGLE_#NAME : C_COND_FT<"ngle", TypeStr, RC, itin>, C_COND_FM<fmt, 9>;
- def C_SEQ_#NAME : C_COND_FT<"seq", TypeStr, RC, itin>, C_COND_FM<fmt, 10>;
- def C_NGL_#NAME : C_COND_FT<"ngl", TypeStr, RC, itin>, C_COND_FM<fmt, 11>;
- def C_LT_#NAME : C_COND_FT<"lt", TypeStr, RC, itin>, C_COND_FM<fmt, 12>;
- def C_NGE_#NAME : C_COND_FT<"nge", TypeStr, RC, itin>, C_COND_FM<fmt, 13>;
- def C_LE_#NAME : C_COND_FT<"le", TypeStr, RC, itin>, C_COND_FM<fmt, 14>;
- def C_NGT_#NAME : C_COND_FT<"ngt", TypeStr, RC, itin>, C_COND_FM<fmt, 15>;
+ def C_F_#NAME : MMRel, C_COND_FT<"f", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 0> {
+ let BaseOpcode = "c.f."#NAME;
+ let isCommutable = 1;
+ }
+ def C_UN_#NAME : MMRel, C_COND_FT<"un", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 1> {
+ let BaseOpcode = "c.un."#NAME;
+ let isCommutable = 1;
+ }
+ def C_EQ_#NAME : MMRel, C_COND_FT<"eq", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 2> {
+ let BaseOpcode = "c.eq."#NAME;
+ let isCommutable = 1;
+ }
+ def C_UEQ_#NAME : MMRel, C_COND_FT<"ueq", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 3> {
+ let BaseOpcode = "c.ueq."#NAME;
+ let isCommutable = 1;
+ }
+ def C_OLT_#NAME : MMRel, C_COND_FT<"olt", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 4> {
+ let BaseOpcode = "c.olt."#NAME;
+ }
+ def C_ULT_#NAME : MMRel, C_COND_FT<"ult", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 5> {
+ let BaseOpcode = "c.ult."#NAME;
+ }
+ def C_OLE_#NAME : MMRel, C_COND_FT<"ole", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 6> {
+ let BaseOpcode = "c.ole."#NAME;
+ }
+ def C_ULE_#NAME : MMRel, C_COND_FT<"ule", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 7> {
+ let BaseOpcode = "c.ule."#NAME;
+ }
+ def C_SF_#NAME : MMRel, C_COND_FT<"sf", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 8> {
+ let BaseOpcode = "c.sf."#NAME;
+ let isCommutable = 1;
+ }
+ def C_NGLE_#NAME : MMRel, C_COND_FT<"ngle", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 9> {
+ let BaseOpcode = "c.ngle."#NAME;
+ }
+ def C_SEQ_#NAME : MMRel, C_COND_FT<"seq", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 10> {
+ let BaseOpcode = "c.seq."#NAME;
+ let isCommutable = 1;
+ }
+ def C_NGL_#NAME : MMRel, C_COND_FT<"ngl", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 11> {
+ let BaseOpcode = "c.ngl."#NAME;
+ }
+ def C_LT_#NAME : MMRel, C_COND_FT<"lt", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 12> {
+ let BaseOpcode = "c.lt."#NAME;
+ }
+ def C_NGE_#NAME : MMRel, C_COND_FT<"nge", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 13> {
+ let BaseOpcode = "c.nge."#NAME;
+ }
+ def C_LE_#NAME : MMRel, C_COND_FT<"le", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 14> {
+ let BaseOpcode = "c.le."#NAME;
+ }
+ def C_NGT_#NAME : MMRel, C_COND_FT<"ngt", TypeStr, RC, itin>,
+ C_COND_FM<fmt, 15> {
+ let BaseOpcode = "c.ngt."#NAME;
+ }
}
+let AdditionalPredicates = [NotInMicroMips] in {
defm S : C_COND_M<"s", FGR32Opnd, 16, II_C_CC_S>, ISA_MIPS1_NOT_32R6_64R6;
defm D32 : C_COND_M<"d", AFGR64Opnd, 17, II_C_CC_D>, ISA_MIPS1_NOT_32R6_64R6,
FGR_32;
let DecoderNamespace = "Mips64" in
defm D64 : C_COND_M<"d", FGR64Opnd, 17, II_C_CC_D>, ISA_MIPS1_NOT_32R6_64R6,
FGR_64;
-
+}
//===----------------------------------------------------------------------===//
// Floating Point Instructions
//===----------------------------------------------------------------------===//
@@ -549,13 +615,29 @@ def BC1TL : MMRel, BC1F_FT<"bc1tl", brtarget, II_BC1TL, MIPS_BRANCH_T, 0>,
/// Floating Point Compare
let AdditionalPredicates = [NotInMicroMips] in {
def FCMP_S32 : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>, CEQS_FM<16>,
- ISA_MIPS1_NOT_32R6_64R6;
+ ISA_MIPS1_NOT_32R6_64R6 {
+
+ // FIXME: This is a required to work around the fact that these instructions
+ // only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the
+ // fcc register set is used directly.
+ bits<3> fcc = 0;
+ }
def FCMP_D32 : MMRel, CEQS_FT<"d", AFGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>,
- ISA_MIPS1_NOT_32R6_64R6, FGR_32;
+ ISA_MIPS1_NOT_32R6_64R6, FGR_32 {
+ // FIXME: This is a required to work around the fact that these instructions
+ // only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the
+ // fcc register set is used directly.
+ bits<3> fcc = 0;
+ }
}
let DecoderNamespace = "Mips64" in
def FCMP_D64 : CEQS_FT<"d", FGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>,
- ISA_MIPS1_NOT_32R6_64R6, FGR_64;
+ ISA_MIPS1_NOT_32R6_64R6, FGR_64 {
+ // FIXME: This is a required to work around the fact that thiese instructions
+ // only use $fcc0. Ideally, MipsFPCmp nodes could be removed and the
+ // fcc register set is used directly.
+ bits<3> fcc = 0;
+}
//===----------------------------------------------------------------------===//
// Floating Point Pseudo-Instructions
@@ -602,15 +684,6 @@ def PseudoTRUNC_W_D : MipsAsmPseudoInst<(outs FGR32Opnd:$fd),
//===----------------------------------------------------------------------===//
// InstAliases.
//===----------------------------------------------------------------------===//
-def : MipsInstAlias<"bc1t $offset", (BC1T FCC0, brtarget:$offset)>,
- ISA_MIPS1_NOT_32R6_64R6, HARDFLOAT;
-def : MipsInstAlias<"bc1tl $offset", (BC1TL FCC0, brtarget:$offset)>,
- ISA_MIPS2_NOT_32R6_64R6, HARDFLOAT;
-def : MipsInstAlias<"bc1f $offset", (BC1F FCC0, brtarget:$offset)>,
- ISA_MIPS1_NOT_32R6_64R6, HARDFLOAT;
-def : MipsInstAlias<"bc1fl $offset", (BC1FL FCC0, brtarget:$offset)>,
- ISA_MIPS2_NOT_32R6_64R6, HARDFLOAT;
-
def : MipsInstAlias
<"s.s $fd, $addr", (SWC1 FGR32Opnd:$fd, mem_simm16:$addr), 0>,
ISA_MIPS2, HARDFLOAT;
@@ -630,6 +703,80 @@ def : MipsInstAlias
def : MipsInstAlias
<"l.d $fd, $addr", (LDC164 FGR64Opnd:$fd, mem_simm16:$addr), 0>,
FGR_64, ISA_MIPS2, HARDFLOAT;
+
+multiclass C_COND_ALIASES<string TypeStr, RegisterOperand RC> {
+ def : MipsInstAlias<!strconcat("c.f.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_F_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.un.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_UN_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.eq.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_EQ_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.ueq.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_UEQ_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.olt.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_OLT_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.ult.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_ULT_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.ole.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_OLE_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.ule.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_ULE_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.sf.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_SF_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.ngle.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_NGLE_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.seq.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_SEQ_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.ngl.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_NGL_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.lt.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_LT_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.nge.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_NGE_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.le.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_LE_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+ def : MipsInstAlias<!strconcat("c.ngt.", TypeStr, " $fs, $ft"),
+ (!cast<Instruction>("C_NGT_"#NAME) FCC0,
+ RC:$fs, RC:$ft), 1>;
+}
+
+multiclass BC1_ALIASES<Instruction BCTrue, string BCTrueString,
+ Instruction BCFalse, string BCFalseString> {
+ def : MipsInstAlias<!strconcat(BCTrueString, " $offset"),
+ (BCTrue FCC0, brtarget:$offset), 1>;
+
+ def : MipsInstAlias<!strconcat(BCFalseString, " $offset"),
+ (BCFalse FCC0, brtarget:$offset), 1>;
+}
+
+let AdditionalPredicates = [NotInMicroMips] in {
+ defm S : C_COND_ALIASES<"s", FGR32Opnd>, HARDFLOAT,
+ ISA_MIPS1_NOT_32R6_64R6;
+ defm D32 : C_COND_ALIASES<"d", AFGR64Opnd>, HARDFLOAT,
+ ISA_MIPS1_NOT_32R6_64R6, FGR_32;
+ defm D64 : C_COND_ALIASES<"d", FGR64Opnd>, HARDFLOAT,
+ ISA_MIPS1_NOT_32R6_64R6, FGR_64;
+
+ defm : BC1_ALIASES<BC1T, "bc1t", BC1F, "bc1f">, ISA_MIPS1_NOT_32R6_64R6,
+ HARDFLOAT;
+ defm : BC1_ALIASES<BC1TL, "bc1tl", BC1FL, "bc1fl">, ISA_MIPS2_NOT_32R6_64R6,
+ HARDFLOAT;
+}
//===----------------------------------------------------------------------===//
// Floating Point Patterns
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td
index 1437fb75434a..817d9b44b9c2 100644
--- a/lib/Target/Mips/MipsInstrFormats.td
+++ b/lib/Target/Mips/MipsInstrFormats.td
@@ -101,12 +101,15 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern,
bit IsPCRelativeLoad = 0; // Load instruction with implicit source register
// ($pc) and with explicit offset and destination
// register
+ bit hasFCCRegOperand = 0; // Instruction uses $fcc<X> register and is
+ // present in MIPS-I to MIPS-III.
- // TSFlags layout should be kept in sync with MipsInstrInfo.h.
+ // TSFlags layout should be kept in sync with MCTargetDesc/MipsBaseInfo.h.
let TSFlags{3-0} = FormBits;
let TSFlags{4} = isCTI;
let TSFlags{5} = hasForbiddenSlot;
let TSFlags{6} = IsPCRelativeLoad;
+ let TSFlags{7} = hasFCCRegOperand;
let DecoderNamespace = "Mips";
@@ -829,6 +832,7 @@ class BC1F_FM<bit nd, bit tf> : StdArch {
class CEQS_FM<bits<5> fmt> : StdArch {
bits<5> fs;
bits<5> ft;
+ bits<3> fcc;
bits<4> cond;
bits<32> Inst;
@@ -837,7 +841,7 @@ class CEQS_FM<bits<5> fmt> : StdArch {
let Inst{25-21} = fmt;
let Inst{20-16} = ft;
let Inst{15-11} = fs;
- let Inst{10-8} = 0; // cc
+ let Inst{10-8} = fcc;
let Inst{7-4} = 0x3;
let Inst{3-0} = cond;
}
diff --git a/lib/Target/Mips/MipsTargetObjectFile.cpp b/lib/Target/Mips/MipsTargetObjectFile.cpp
index fadab7806120..c5d6a05d6611 100644
--- a/lib/Target/Mips/MipsTargetObjectFile.cpp
+++ b/lib/Target/Mips/MipsTargetObjectFile.cpp
@@ -148,3 +148,11 @@ MCSection *MipsTargetObjectFile::getSectionForConstant(const DataLayout &DL,
// Otherwise, we work the same as ELF.
return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, Align);
}
+
+const MCExpr *
+MipsTargetObjectFile::getDebugThreadLocalSymbol(const MCSymbol *Sym) const {
+ const MCExpr *Expr =
+ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+ return MCBinaryExpr::createAdd(
+ Expr, MCConstantExpr::create(0x8000, getContext()), getContext());
+}
diff --git a/lib/Target/Mips/MipsTargetObjectFile.h b/lib/Target/Mips/MipsTargetObjectFile.h
index e5423f9578a8..a37ec154ff79 100644
--- a/lib/Target/Mips/MipsTargetObjectFile.h
+++ b/lib/Target/Mips/MipsTargetObjectFile.h
@@ -42,6 +42,8 @@ class MipsTargetMachine;
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
const Constant *C,
unsigned &Align) const override;
+ /// Describe a TLS variable address within debug info.
+ const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const override;
};
} // end namespace llvm
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index 90111bbea07d..f615cc7cc974 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/lib/Target/PowerPC/PPCInstrInfo.td
@@ -1508,8 +1508,14 @@ def DCBTST : DCB_Form_hint<246, (outs), (ins u5imm:$TH, memrr:$dst),
PPC970_DGroup_Single;
} // hasSideEffects = 0
+def ICBLC : XForm_icbt<31, 230, (outs), (ins u4imm:$CT, memrr:$src),
+ "icblc $CT, $src", IIC_LdStStore>, Requires<[HasICBT]>;
+def ICBLQ : XForm_icbt<31, 198, (outs), (ins u4imm:$CT, memrr:$src),
+ "icblq. $CT, $src", IIC_LdStLoad>, Requires<[HasICBT]>;
def ICBT : XForm_icbt<31, 22, (outs), (ins u4imm:$CT, memrr:$src),
"icbt $CT, $src", IIC_LdStLoad>, Requires<[HasICBT]>;
+def ICBTLS : XForm_icbt<31, 486, (outs), (ins u4imm:$CT, memrr:$src),
+ "icbtls $CT, $src", IIC_LdStLoad>, Requires<[HasICBT]>;
def : Pat<(int_ppc_dcbt xoaddr:$dst),
(DCBT 0, xoaddr:$dst)>;
@@ -2381,6 +2387,13 @@ def MTSPR : XFXForm_1<31, 467, (outs), (ins i32imm:$SPR, gprc:$RT),
def MFTB : XFXForm_1<31, 371, (outs gprc:$RT), (ins i32imm:$SPR),
"mftb $RT, $SPR", IIC_SprMFTB>;
+def MFPMR : XFXForm_1<31, 334, (outs gprc:$RT), (ins i32imm:$SPR),
+ "mfpmr $RT, $SPR", IIC_SprMFPMR>;
+
+def MTPMR : XFXForm_1<31, 462, (outs), (ins i32imm:$SPR, gprc:$RT),
+ "mtpmr $SPR, $RT", IIC_SprMTPMR>;
+
+
// A pseudo-instruction used to implement the read of the 64-bit cycle counter
// on a 32-bit target.
let hasSideEffects = 1, usesCustomInserter = 1 in
diff --git a/lib/Target/PowerPC/PPCSchedule.td b/lib/Target/PowerPC/PPCSchedule.td
index edabe7748673..d240529bc731 100644
--- a/lib/Target/PowerPC/PPCSchedule.td
+++ b/lib/Target/PowerPC/PPCSchedule.td
@@ -118,6 +118,8 @@ def IIC_SprTLBIE : InstrItinClass;
def IIC_SprABORT : InstrItinClass;
def IIC_SprMSGSYNC : InstrItinClass;
def IIC_SprSTOP : InstrItinClass;
+def IIC_SprMFPMR : InstrItinClass;
+def IIC_SprMTPMR : InstrItinClass;
//===----------------------------------------------------------------------===//
// Processor instruction itineraries.
diff --git a/lib/Target/PowerPC/PPCScheduleE500mc.td b/lib/Target/PowerPC/PPCScheduleE500mc.td
index f687d326b52d..15d5991b938c 100644
--- a/lib/Target/PowerPC/PPCScheduleE500mc.td
+++ b/lib/Target/PowerPC/PPCScheduleE500mc.td
@@ -249,6 +249,10 @@ def PPCE500mcItineraries : ProcessorItineraries<
InstrStage<5, [E500_SFX0]>],
[8, 1],
[E500_GPR_Bypass, E500_CR_Bypass]>,
+ InstrItinData<IIC_SprMFPMR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>,
+ InstrStage<4, [E500_SFX0]>],
+ [7, 1], // Latency = 4, Repeat rate = 4
+ [E500_GPR_Bypass, E500_GPR_Bypass]>,
InstrItinData<IIC_SprMFMSR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>,
InstrStage<4, [E500_SFX0]>],
[7, 1], // Latency = 4, Repeat rate = 4
@@ -257,6 +261,10 @@ def PPCE500mcItineraries : ProcessorItineraries<
InstrStage<1, [E500_SFX0, E500_SFX1]>],
[4, 1], // Latency = 1, Repeat rate = 1
[E500_GPR_Bypass, E500_CR_Bypass]>,
+ InstrItinData<IIC_SprMTPMR, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>,
+ InstrStage<1, [E500_SFX0]>],
+ [4, 1], // Latency = 1, Repeat rate = 1
+ [E500_CR_Bypass, E500_GPR_Bypass]>,
InstrItinData<IIC_SprMFTB, [InstrStage<1, [E500_DIS0, E500_DIS1], 0>,
InstrStage<4, [E500_SFX0]>],
[7, 1], // Latency = 4, Repeat rate = 4
diff --git a/lib/Target/PowerPC/PPCScheduleE5500.td b/lib/Target/PowerPC/PPCScheduleE5500.td
index 5db886cf8f94..32f8e652dd56 100644
--- a/lib/Target/PowerPC/PPCScheduleE5500.td
+++ b/lib/Target/PowerPC/PPCScheduleE5500.td
@@ -313,20 +313,24 @@ def PPCE5500Itineraries : ProcessorItineraries<
InstrStage<5, [E5500_CFX_0]>],
[9, 2], // Latency = 5, Repeat rate = 5
[E5500_GPR_Bypass, E5500_CR_Bypass]>,
- InstrItinData<IIC_SprMFMSR, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
- InstrStage<4, [E5500_SFX0]>],
+ InstrItinData<IIC_SprMFPMR, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
+ InstrStage<4, [E5500_CFX_0]>],
[8, 2], // Latency = 4, Repeat rate = 4
[E5500_GPR_Bypass, E5500_GPR_Bypass]>,
InstrItinData<IIC_SprMFSPR, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
InstrStage<1, [E5500_CFX_0]>],
[5], // Latency = 1, Repeat rate = 1
[E5500_GPR_Bypass]>,
+ InstrItinData<IIC_SprMTPMR, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
+ InstrStage<1, [E5500_CFX_0]>],
+ [5], // Latency = 1, Repeat rate = 1
+ [E5500_GPR_Bypass]>,
InstrItinData<IIC_SprMFTB, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
InstrStage<4, [E5500_CFX_0]>],
[8, 2], // Latency = 4, Repeat rate = 4
[NoBypass, E5500_GPR_Bypass]>,
InstrItinData<IIC_SprMTSPR, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,
- InstrStage<1, [E5500_SFX0, E5500_SFX1]>],
+ InstrStage<1, [E5500_CFX_0]>],
[5], // Latency = 1, Repeat rate = 1
[E5500_GPR_Bypass]>,
InstrItinData<IIC_FPGeneral, [InstrStage<1, [E5500_DIS0, E5500_DIS1], 0>,