Merge commit 7bed381ea from llvm git (by Simon Atanasyan):
[mips] Implement Octeon+ `saa` and `saad` instructions `saa` and `saad` are 32-bit and 64-bit store atomic add instructions. memory[base] = memory[base] + rt These instructions are available for "Octeon+" CPU. The patch adds support for both instructions to MIPS assembler and diassembler and introduces new CPU type - "octeon+". Next patches will implement `.set arch=octeon+` directive and `AFL_EXT_OCTEONP` ISA extension flag support. Differential Revision: https://reviews.llvm.org/D69849 This is one of the upstream changes needed for adding support for the OCTEON+ CPU type, so that we can test Clang builds using the most commonly available FreeBSD/mips64 reference platform, the Edge Router Lite. Requested by: kevans MFC after: 1 month X-MFC-With: r353358
This commit is contained in:
parent
964c4a37b0
commit
2967f08a40
@ -125,7 +125,8 @@ const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = {
|
||||
Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6,
|
||||
Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3,
|
||||
Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips,
|
||||
Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008
|
||||
Mips::FeatureCnMipsP, Mips::FeatureFP64Bit, Mips::FeatureGP64Bit,
|
||||
Mips::FeatureNaN2008
|
||||
};
|
||||
|
||||
namespace {
|
||||
@ -324,6 +325,9 @@ class MipsAsmParser : public MCTargetAsmParser {
|
||||
bool expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
|
||||
const MCSubtargetInfo *STI);
|
||||
|
||||
bool expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
|
||||
const MCSubtargetInfo *STI);
|
||||
|
||||
bool reportParseError(Twine ErrorMsg);
|
||||
bool reportParseError(SMLoc Loc, Twine ErrorMsg);
|
||||
|
||||
@ -648,6 +652,10 @@ class MipsAsmParser : public MCTargetAsmParser {
|
||||
return (getSTI().getFeatureBits()[Mips::FeatureCnMips]);
|
||||
}
|
||||
|
||||
bool hasCnMipsP() const {
|
||||
return (getSTI().getFeatureBits()[Mips::FeatureCnMipsP]);
|
||||
}
|
||||
|
||||
bool inPicMode() {
|
||||
return IsPicEnabled;
|
||||
}
|
||||
@ -2584,6 +2592,9 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
|
||||
case Mips::MFTHC1: case Mips::MTTHC1:
|
||||
case Mips::CFTC1: case Mips::CTTC1:
|
||||
return expandMXTRAlias(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
|
||||
case Mips::SaaAddr:
|
||||
case Mips::SaadAddr:
|
||||
return expandSaaAddr(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3074,7 +3085,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
||||
TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
|
||||
|
||||
return false;
|
||||
} else if (canUseATReg() && !RdRegIsRsReg) {
|
||||
} else if (canUseATReg() && !RdRegIsRsReg && DstReg != getATReg(IDLoc)) {
|
||||
unsigned ATReg = getATReg(IDLoc);
|
||||
|
||||
// If the $rs is different from $rd or if $rs isn't specified and we
|
||||
@ -3101,7 +3112,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
||||
TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
|
||||
|
||||
return false;
|
||||
} else if (!canUseATReg() && !RdRegIsRsReg) {
|
||||
} else if ((!canUseATReg() && !RdRegIsRsReg) ||
|
||||
(canUseATReg() && DstReg == getATReg(IDLoc))) {
|
||||
// Otherwise, synthesize the address in the destination register
|
||||
// serially:
|
||||
// (d)la $rd, sym/sym($rs) => lui $rd, %highest(sym)
|
||||
@ -5359,6 +5371,39 @@ bool MipsAsmParser::expandMXTRAlias(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MipsAsmParser::expandSaaAddr(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
|
||||
const MCSubtargetInfo *STI) {
|
||||
assert(Inst.getNumOperands() == 3 && "expected three operands");
|
||||
assert(Inst.getOperand(0).isReg() && "expected register operand kind");
|
||||
assert(Inst.getOperand(1).isReg() && "expected register operand kind");
|
||||
|
||||
warnIfNoMacro(IDLoc);
|
||||
|
||||
MipsTargetStreamer &TOut = getTargetStreamer();
|
||||
unsigned Opcode = Inst.getOpcode() == Mips::SaaAddr ? Mips::SAA : Mips::SAAD;
|
||||
unsigned RtReg = Inst.getOperand(0).getReg();
|
||||
unsigned BaseReg = Inst.getOperand(1).getReg();
|
||||
const MCOperand &BaseOp = Inst.getOperand(2);
|
||||
|
||||
if (BaseOp.isImm()) {
|
||||
int64_t ImmValue = BaseOp.getImm();
|
||||
if (ImmValue == 0) {
|
||||
TOut.emitRR(Opcode, RtReg, BaseReg, IDLoc, STI);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned ATReg = getATReg(IDLoc);
|
||||
if (!ATReg)
|
||||
return true;
|
||||
|
||||
if (expandLoadAddress(ATReg, BaseReg, BaseOp, !isGP64bit(), IDLoc, Out, STI))
|
||||
return true;
|
||||
|
||||
TOut.emitRR(Opcode, RtReg, ATReg, IDLoc, STI);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned
|
||||
MipsAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst,
|
||||
const OperandVector &Operands) {
|
||||
|
@ -63,6 +63,8 @@ class MipsDisassembler : public MCDisassembler {
|
||||
|
||||
bool hasCnMips() const { return STI.getFeatureBits()[Mips::FeatureCnMips]; }
|
||||
|
||||
bool hasCnMipsP() const { return STI.getFeatureBits()[Mips::FeatureCnMipsP]; }
|
||||
|
||||
bool hasCOP3() const {
|
||||
// Only present in MIPS-I and MIPS-II
|
||||
return !hasMips32() && !hasMips3();
|
||||
@ -1346,6 +1348,14 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
|
||||
return Result;
|
||||
}
|
||||
|
||||
if (hasCnMipsP()) {
|
||||
LLVM_DEBUG(dbgs() << "Trying CnMipsP table (32-bit opcodes):\n");
|
||||
Result = decodeInstruction(DecoderTableCnMipsP32, Instr, Insn,
|
||||
Address, this, STI);
|
||||
if (Result != MCDisassembler::Fail)
|
||||
return Result;
|
||||
}
|
||||
|
||||
if (isGP64()) {
|
||||
LLVM_DEBUG(dbgs() << "Trying Mips64 (GPR64) table (32-bit opcodes):\n");
|
||||
Result = decodeInstruction(DecoderTableMips6432, Instr, Insn,
|
||||
|
@ -193,6 +193,10 @@ def FeatureCnMips : SubtargetFeature<"cnmips", "HasCnMips",
|
||||
"true", "Octeon cnMIPS Support",
|
||||
[FeatureMips64r2]>;
|
||||
|
||||
def FeatureCnMipsP : SubtargetFeature<"cnmipsp", "HasCnMipsP",
|
||||
"true", "Octeon+ cnMIPS Support",
|
||||
[FeatureCnMips]>;
|
||||
|
||||
def FeatureUseTCCInDIV : SubtargetFeature<
|
||||
"use-tcc-in-div",
|
||||
"UseTCCInDIV", "false",
|
||||
@ -238,6 +242,7 @@ def : Proc<"mips64r3", [FeatureMips64r3]>;
|
||||
def : Proc<"mips64r5", [FeatureMips64r5]>;
|
||||
def : Proc<"mips64r6", [FeatureMips64r6]>;
|
||||
def : Proc<"octeon", [FeatureMips64r2, FeatureCnMips]>;
|
||||
def : Proc<"octeon+", [FeatureMips64r2, FeatureCnMips, FeatureCnMipsP]>;
|
||||
def : ProcessorModel<"p5600", MipsP5600Model, [ImplP5600]>;
|
||||
|
||||
def MipsAsmParser : AsmParser {
|
||||
|
@ -585,6 +585,24 @@ def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd, II_DMTC2>, MFC2OP_FM<0x12, 5>,
|
||||
ASE_CNMIPS;
|
||||
}
|
||||
|
||||
// Cavium Octeon+ cnMIPS instructions
|
||||
let DecoderNamespace = "CnMipsP",
|
||||
// FIXME: The lack of HasStdEnc is probably a bug
|
||||
EncodingPredicates = []<Predicate> in {
|
||||
|
||||
class Saa<string opstr>:
|
||||
InstSE<(outs), (ins GPR64Opnd:$rt, GPR64Opnd:$rs),
|
||||
!strconcat(opstr, "\t$rt, (${rs})"), [], NoItinerary, FrmR, opstr>;
|
||||
|
||||
def SAA : Saa<"saa">, SAA_FM<0x18>, ASE_CNMIPSP;
|
||||
def SAAD : Saa<"saad">, SAA_FM<0x19>, ASE_CNMIPSP;
|
||||
|
||||
def SaaAddr : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rt, mem:$addr),
|
||||
"saa\t$rt, $addr">, ASE_CNMIPSP;
|
||||
def SaadAddr : MipsAsmPseudoInst<(outs), (ins GPR64Opnd:$rt, mem:$addr),
|
||||
"saad\t$rt, $addr">, ASE_CNMIPSP;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Move between CPU and coprocessor registers
|
||||
|
@ -626,6 +626,19 @@ class SEQI_FM<bits<6> funct> : StdArch {
|
||||
let Inst{5-0} = funct;
|
||||
}
|
||||
|
||||
class SAA_FM<bits<6> funct> : StdArch {
|
||||
bits<5> rt;
|
||||
bits<5> rs;
|
||||
|
||||
bits<32> Inst;
|
||||
|
||||
let Inst{31-26} = 0x1c;
|
||||
let Inst{25-21} = rs;
|
||||
let Inst{20-16} = rt;
|
||||
let Inst{15-6} = 0;
|
||||
let Inst{5-0} = funct;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// System calls format <op|code_|funct>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -211,6 +211,10 @@ def HasCnMips : Predicate<"Subtarget->hasCnMips()">,
|
||||
AssemblerPredicate<"FeatureCnMips">;
|
||||
def NotCnMips : Predicate<"!Subtarget->hasCnMips()">,
|
||||
AssemblerPredicate<"!FeatureCnMips">;
|
||||
def HasCnMipsP : Predicate<"Subtarget->hasCnMipsP()">,
|
||||
AssemblerPredicate<"FeatureCnMipsP">;
|
||||
def NotCnMipsP : Predicate<"!Subtarget->hasCnMipsP()">,
|
||||
AssemblerPredicate<"!FeatureCnMipsP">;
|
||||
def IsSym32 : Predicate<"Subtarget->HasSym32()">,
|
||||
AssemblerPredicate<"FeatureSym32">;
|
||||
def IsSym64 : Predicate<"!Subtarget->HasSym32()">,
|
||||
@ -439,6 +443,14 @@ class NOT_ASE_CNMIPS {
|
||||
list<Predicate> ASEPredicate = [NotCnMips];
|
||||
}
|
||||
|
||||
class ASE_CNMIPSP {
|
||||
list<Predicate> ASEPredicate = [HasCnMipsP];
|
||||
}
|
||||
|
||||
class NOT_ASE_CNMIPSP {
|
||||
list<Predicate> ASEPredicate = [NotCnMipsP];
|
||||
}
|
||||
|
||||
class ASE_MIPS64_CNMIPS {
|
||||
list<Predicate> ASEPredicate = [HasMips64, HasCnMips];
|
||||
}
|
||||
|
@ -720,11 +720,16 @@ def : InstRW<[GenericWriteALU], (instrs BADDu, BBIT0, BBIT032, BBIT1, BBIT132,
|
||||
CINS, CINS32, CINS64_32, CINS_i32,
|
||||
DMFC2_OCTEON, DMTC2_OCTEON, DPOP, EXTS,
|
||||
EXTS32, MTM0, MTM1, MTM2, MTP0, MTP1, MTP2,
|
||||
POP, SEQ, SEQi, SNE, SNEi, V3MULU, VMM0,
|
||||
VMULU)>;
|
||||
POP, SEQ, SEQi, SNE, SNEi,
|
||||
V3MULU, VMM0, VMULU)>;
|
||||
|
||||
def : InstRW<[GenericWriteMDUtoGPR], (instrs DMUL)>;
|
||||
|
||||
// Cavium Networks MIPS (cnMIPSP) - Octeon+, HasCnMipsP
|
||||
// =================================================
|
||||
|
||||
def : InstRW<[GenericWriteALU], (instrs SAA, SAAD)>;
|
||||
|
||||
// FPU Pipelines
|
||||
// =============
|
||||
|
||||
|
@ -18,7 +18,8 @@ def MipsP5600Model : SchedMachineModel {
|
||||
list<Predicate> UnsupportedFeatures = [HasMips3, HasMips32r6, HasMips64,
|
||||
HasMips64r2, HasMips64r5, HasMips64r6,
|
||||
IsGP64bit, IsPTR64bit,
|
||||
InMicroMips, InMips16Mode, HasCnMips,
|
||||
InMicroMips, InMips16Mode,
|
||||
HasCnMips, HasCnMipsP,
|
||||
HasDSP, HasDSPR2, HasMT, HasCRC];
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
|
||||
// CPU supports cnMIPS (Cavium Networks Octeon CPU).
|
||||
bool HasCnMips;
|
||||
|
||||
// CPU supports cnMIPSP (Cavium Networks Octeon+ CPU).
|
||||
bool HasCnMipsP;
|
||||
|
||||
// isLinux - Target system is Linux. Is false we consider ELFOS for now.
|
||||
bool IsLinux;
|
||||
|
||||
@ -267,6 +270,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
|
||||
bool hasMips64r6() const { return MipsArchVersion >= Mips64r6; }
|
||||
|
||||
bool hasCnMips() const { return HasCnMips; }
|
||||
bool hasCnMipsP() const { return HasCnMipsP; }
|
||||
|
||||
bool isLittle() const { return IsLittle; }
|
||||
bool isABICalls() const { return !NoABICalls; }
|
||||
|
Loading…
Reference in New Issue
Block a user