#define DEBUG_TYPE "sched"
#include "PPCHazardRecognizers.h"
#include "PPC.h"
+#include "PPCInstrInfo.h"
#include "llvm/Support/Debug.h"
#include <iostream>
using namespace llvm;
// PowerPC 970 Hazard Recognizer
//
// This models the dispatch group formation of the PPC970 processor. Dispatch
-// groups are bundles of up to five instructions that can contain up to two ALU
-// (aka FXU) ops, two FPU ops, two Load/Store ops, one CR op, one VALU op, one
-// VPERM op, and one BRANCH op. If the code contains more instructions in a
-// sequence than the dispatch group can contain (e.g. three loads in a row) the
-// processor terminates the dispatch group early, wasting execution resources.
+// groups are bundles of up to five instructions that can contain various mixes
+// of instructions. The PPC970 can dispatch a peak of 4 non-branch and one
+// branch instruction per-cycle.
//
-// In addition to these restrictions, there are a number of other restrictions:
-// some instructions, e.g. branches, are required to be the last instruction in
-// a group. Additionally, only branches can issue in the 5th (last) slot.
+// There are a number of restrictions to dispatch group formation: some
+// instructions can only be issued in the first slot of a dispatch group, & some
+// instructions fill an entire dispatch group. Additionally, only branches can
+// issue in the 5th (last) slot.
//
// Finally, there are a number of "structural" hazards on the PPC970. These
// conditions cause large performance penalties due to misprediction, recovery,
// conditions, we insert no-op instructions when appropriate.
//
// FIXME: This is missing some significant cases:
-// -1. Handle all of the instruction types in GetInstrType.
-// 0. Handling of instructions that must be the first/last in a group.
// 1. Modeling of microcoded instructions.
// 2. Handling of cracked instructions.
// 3. Handling of serialized operations.
// e.g. integer divides that only execute in the second slot.
//
-PPCHazardRecognizer970::PPCHazardRecognizer970() {
+PPCHazardRecognizer970::PPCHazardRecognizer970(const TargetInstrInfo &tii)
+ : TII(tii) {
EndDispatchGroup();
}
void PPCHazardRecognizer970::EndDispatchGroup() {
DEBUG(std::cerr << "=== Start of dispatch group\n");
- // Pipeline units.
- NumFXU = NumLSU = NumFPU = 0;
- HasCR = HasSPR = HasVALU = HasVPERM = false;
NumIssued = 0;
// Structural hazard info.
HasCTRSet = false;
- StorePtr1 = StorePtr2 = SDOperand();
- StoreSize = 0;
+ NumStores = 0;
}
-PPCHazardRecognizer970::PPC970InstrType
-PPCHazardRecognizer970::GetInstrType(unsigned Opcode) {
- if (Opcode < ISD::BUILTIN_OP_END)
- return PseudoInst;
+PPCII::PPC970_Unit
+PPCHazardRecognizer970::GetInstrType(unsigned Opcode,
+ bool &isFirst, bool &isSingle,
+ bool &isLoad, bool &isStore){
+ if (Opcode < ISD::BUILTIN_OP_END) {
+ isFirst = isSingle = isLoad = isStore = false;
+ return PPCII::PPC970_Pseudo;
+ }
Opcode -= ISD::BUILTIN_OP_END;
- switch (Opcode) {
- case PPC::FMRSD: return PseudoInst; // Usually coallesced away.
- case PPC::BCTRL:
- case PPC::BL:
- case PPC::BLA:
- case PPC::BLR:
- return BR;
- case PPC::MCRF:
- case PPC::MFCR:
- case PPC::MFOCRF:
- return CR;
- case PPC::MFLR:
- case PPC::MFCTR:
- case PPC::MTLR:
- case PPC::MTCTR:
- return SPR;
- case PPC::LFS:
- case PPC::LFD:
- case PPC::LWZ:
- case PPC::LFSX:
- case PPC::LWZX:
- case PPC::LBZ:
- case PPC::LHA:
- case PPC::LHZ:
- case PPC::LWZU:
- return LSU_LD;
- case PPC::STFS:
- case PPC::STFD:
- case PPC::STW:
- case PPC::STB:
- case PPC::STH:
- case PPC::STWU:
- return LSU_ST;
- case PPC::DIVW:
- case PPC::DIVWU:
- case PPC::DIVD:
- case PPC::DIVDU:
- return FXU_FIRST;
- case PPC::FADDS:
- case PPC::FCTIWZ:
- case PPC::FRSP:
- case PPC::FSUB:
- return FPU;
- }
+ const TargetInstrDescriptor &TID = TII.get(Opcode);
+
+ isLoad = TID.Flags & M_LOAD_FLAG;
+ isStore = TID.Flags & M_STORE_FLAG;
- return FXU;
+ unsigned TSFlags = TID.TSFlags;
+
+ isFirst = TSFlags & PPCII::PPC970_First;
+ isSingle = TSFlags & PPCII::PPC970_Single;
+ return (PPCII::PPC970_Unit)(TSFlags & PPCII::PPC970_Mask);
}
/// isLoadOfStoredAddress - If we have a load from the previously stored pointer
/// as indicated by StorePtr1/StorePtr2/StoreSize, return true.
bool PPCHazardRecognizer970::
isLoadOfStoredAddress(unsigned LoadSize, SDOperand Ptr1, SDOperand Ptr2) const {
- // Handle exact and commuted addresses.
- if (Ptr1 == StorePtr1 && Ptr2 == StorePtr2)
- return true;
- if (Ptr2 == StorePtr1 && Ptr1 == StorePtr2)
- return true;
-
- // Okay, we don't have an exact match, if this is an indexed offset, see if we
- // have overlap (which happens during fp->int conversion for example).
- if (StorePtr2 == Ptr2) {
- if (ConstantSDNode *StoreOffset = dyn_cast<ConstantSDNode>(StorePtr1))
- if (ConstantSDNode *LoadOffset = dyn_cast<ConstantSDNode>(Ptr1)) {
- // Okay the base pointers match, so we have [c1+r] vs [c2+r]. Check to
- // see if the load and store actually overlap.
- int StoreOffs = StoreOffset->getValue();
- int LoadOffs = LoadOffset->getValue();
- if (StoreOffs < LoadOffs) {
- if (int(StoreOffs+StoreSize) > LoadOffs) return true;
- } else {
- if (int(LoadOffs+LoadSize) > StoreOffs) return true;
+ for (unsigned i = 0, e = NumStores; i != e; ++i) {
+ // Handle exact and commuted addresses.
+ if (Ptr1 == StorePtr1[i] && Ptr2 == StorePtr2[i])
+ return true;
+ if (Ptr2 == StorePtr1[i] && Ptr1 == StorePtr2[i])
+ return true;
+
+ // Okay, we don't have an exact match, if this is an indexed offset, see if
+ // we have overlap (which happens during fp->int conversion for example).
+ if (StorePtr2[i] == Ptr2) {
+ if (ConstantSDNode *StoreOffset = dyn_cast<ConstantSDNode>(StorePtr1[i]))
+ if (ConstantSDNode *LoadOffset = dyn_cast<ConstantSDNode>(Ptr1)) {
+ // Okay the base pointers match, so we have [c1+r] vs [c2+r]. Check
+ // to see if the load and store actually overlap.
+ int StoreOffs = StoreOffset->getValue();
+ int LoadOffs = LoadOffset->getValue();
+ if (StoreOffs < LoadOffs) {
+ if (int(StoreOffs+StoreSize) > LoadOffs) return true;
+ } else {
+ if (int(LoadOffs+LoadSize) > StoreOffs) return true;
+ }
}
- }
+ }
}
return false;
}
/// pipeline flush.
HazardRecognizer::HazardType PPCHazardRecognizer970::
getHazardType(SDNode *Node) {
- PPC970InstrType InstrType = GetInstrType(Node->getOpcode());
- if (InstrType == PseudoInst) return NoHazard;
+ bool isFirst, isSingle, isLoad, isStore;
+ PPCII::PPC970_Unit InstrType =
+ GetInstrType(Node->getOpcode(), isFirst, isSingle, isLoad, isStore);
+ if (InstrType == PPCII::PPC970_Pseudo) return NoHazard;
unsigned Opcode = Node->getOpcode()-ISD::BUILTIN_OP_END;
+ // We can only issue a PPC970_First/PPC970_Single instruction (such as
+ // crand/mtspr/etc) if this is the first cycle of the dispatch group.
+ if (NumIssued != 0 && (isFirst || isSingle) )
+ return Hazard;
+
switch (InstrType) {
default: assert(0 && "Unknown instruction type!");
- case FXU:
- case FXU_FIRST: if (NumFXU == 2) return Hazard;
- case LSU_ST:
- case LSU_LD: if (NumLSU == 2) return Hazard;
- case FPU: if (NumFPU == 2) return Hazard;
- case CR: if (HasCR) return Hazard;
- case SPR: if (HasSPR) return Hazard;
- case VALU: if (HasVALU) return Hazard;
- case VPERM: if (HasVPERM) return Hazard;
- case BR: break;
+ case PPCII::PPC970_FXU:
+ case PPCII::PPC970_LSU:
+ case PPCII::PPC970_FPU:
+ case PPCII::PPC970_VALU:
+ case PPCII::PPC970_VPERM:
+ // We can only issue a branch as the last instruction in a group.
+ if (NumIssued == 4) return Hazard;
+ break;
+ case PPCII::PPC970_CRU:
+ // We can only issue a CR instruction in the first two slots.
+ if (NumIssued >= 2) return Hazard;
+ break;
+ case PPCII::PPC970_BRU:
+ break;
}
-
- // We can only issue a CR or SPR instruction, or an FXU instruction that needs
- // to lead a dispatch group as the first instruction in the group.
- if (NumIssued != 0 &&
- (InstrType == CR || InstrType == SPR || InstrType == FXU_FIRST))
- return Hazard;
-
- // We can only issue a branch as the last instruction in a group.
- if (NumIssued == 4 && InstrType != BR)
- return Hazard;
-
+
// Do not allow MTCTR and BCTRL to be in the same dispatch group.
if (HasCTRSet && Opcode == PPC::BCTRL)
return NoopHazard;
// If this is a load following a store, make sure it's not to the same or
// overlapping address.
- if (InstrType == LSU_LD && StoreSize) {
+ if (isLoad && StoreSize) {
unsigned LoadSize;
switch (Opcode) {
default: assert(0 && "Unknown load!");
- case PPC::LBZ: LoadSize = 1; break;
+ case PPC::LBZ:
+ case PPC::LBZX:
+ case PPC::LVEBX:
+ LoadSize = 1;
+ break;
case PPC::LHA:
- case PPC::LHZ: LoadSize = 2; break;
- case PPC::LWZU:
- case PPC::LFSX:
+ case PPC::LHAX:
+ case PPC::LHZ:
+ case PPC::LHZX:
+ case PPC::LVEHX:
+ LoadSize = 2;
+ break;
case PPC::LFS:
+ case PPC::LFSX:
+ case PPC::LWZ:
case PPC::LWZX:
- case PPC::LWZ: LoadSize = 4; break;
- case PPC::LFD: LoadSize = 8; break;
+ case PPC::LWZU:
+ case PPC::LWA:
+ case PPC::LWAX:
+ case PPC::LVEWX:
+ LoadSize = 4;
+ break;
+ case PPC::LFD:
+ case PPC::LFDX:
+ case PPC::LD:
+ case PPC::LDX:
+ LoadSize = 8;
+ break;
+ case PPC::LVX:
+ LoadSize = 16;
+ break;
}
if (isLoadOfStoredAddress(LoadSize,
}
void PPCHazardRecognizer970::EmitInstruction(SDNode *Node) {
- PPC970InstrType InstrType = GetInstrType(Node->getOpcode());
- if (InstrType == PseudoInst) return;
+ bool isFirst, isSingle, isLoad, isStore;
+ PPCII::PPC970_Unit InstrType =
+ GetInstrType(Node->getOpcode(), isFirst, isSingle, isLoad, isStore);
+ if (InstrType == PPCII::PPC970_Pseudo) return;
unsigned Opcode = Node->getOpcode()-ISD::BUILTIN_OP_END;
// Update structural hazard information.
if (Opcode == PPC::MTCTR) HasCTRSet = true;
// Track the address stored to.
- if (InstrType == LSU_ST) {
- StorePtr1 = Node->getOperand(1);
- StorePtr2 = Node->getOperand(2);
+ if (isStore) {
+ unsigned ThisStoreSize;
switch (Opcode) {
default: assert(0 && "Unknown store instruction!");
- case PPC::STB: StoreSize = 1; break;
- case PPC::STH: StoreSize = 2; break;
+ case PPC::STBX:
+ case PPC::STB:
+ case PPC::STVEBX:
+ ThisStoreSize = 1;
+ break;
+ case PPC::STHX:
+ case PPC::STH:
+ case PPC::STVEHX:
+ ThisStoreSize = 2;
+ break;
case PPC::STFS:
+ case PPC::STFSX:
case PPC::STWU:
- case PPC::STW: StoreSize = 4; break;
- case PPC::STFD: StoreSize = 8; break;
+ case PPC::STWX:
+ case PPC::STWUX:
+ case PPC::STW:
+ case PPC::STVEWX:
+ case PPC::STFIWX:
+ ThisStoreSize = 4;
+ break;
+ case PPC::STD:
+ case PPC::STDU:
+ case PPC::STFD:
+ case PPC::STFDX:
+ case PPC::STDX:
+ case PPC::STDUX:
+ ThisStoreSize = 8;
+ break;
+ case PPC::STVX:
+ ThisStoreSize = 16;
+ break;
}
+
+ StoreSize[NumStores] = ThisStoreSize;
+ StorePtr1[NumStores] = Node->getOperand(1);
+ StorePtr2[NumStores] = Node->getOperand(2);
+ ++NumStores;
}
- switch (InstrType) {
- default: assert(0 && "Unknown instruction type!");
- case FXU:
- case FXU_FIRST: ++NumFXU; break;
- case LSU_LD:
- case LSU_ST: ++NumLSU; break;
- case FPU: ++NumFPU; break;
- case CR: HasCR = true; break;
- case SPR: HasSPR = true; break;
- case VALU: HasVALU = true; break;
- case VPERM: HasVPERM = true; break;
- case BR: NumIssued = 4; return; // ends a d-group.
- }
+ if (InstrType == PPCII::PPC970_BRU || isSingle)
+ NumIssued = 4; // Terminate a d-group.
++NumIssued;
if (NumIssued == 5)
// Pseudo-instructions:
-let isLoad = 1, hasCtrlDep = 1 in {
+let hasCtrlDep = 1 in {
def ADJCALLSTACKDOWN : Pseudo<(ops u16imm:$amt),
"; ADJCALLSTACKDOWN",
[(callseq_start imm:$amt)]>;
// SELECT_CC_* - Used to implement the SELECT_CC DAG operation. Expanded by the
// scheduler into a branch sequence.
-let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler.
+let usesCustomDAGSchedInserter = 1, // Expanded by the scheduler.
+ PPC970_Single = 1 in {
def SELECT_CC_Int : Pseudo<(ops GPRC:$dst, CRRC:$cond, GPRC:$T, GPRC:$F,
i32imm:$BROPC), "; SELECT_CC PSEUDO!", []>;
def SELECT_CC_F4 : Pseudo<(ops F4RC:$dst, CRRC:$cond, F4RC:$T, F4RC:$F,
i32imm:$BROPC), "; SELECT_CC PSEUDO!", []>;
}
-let isTerminator = 1, noResults = 1 in {
+let isTerminator = 1, noResults = 1, PPC970_Unit = 7 in {
let isReturn = 1 in
def BLR : XLForm_2_ext<19, 16, 20, 0, 0, (ops), "blr", BrB, [(retflag)]>;
def BCTR : XLForm_2_ext<19, 528, 20, 0, 0, (ops), "bctr", BrB, []>;
}
let Defs = [LR] in
- def MovePCtoLR : Pseudo<(ops piclabel:$label), "bl $label", []>;
+ def MovePCtoLR : Pseudo<(ops piclabel:$label), "bl $label", []>,
+ PPC970_Unit_BRU;
-let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, noResults = 1 in {
+let isBranch = 1, isTerminator = 1, hasCtrlDep = 1,
+ noResults = 1, PPC970_Unit = 7 in {
def COND_BRANCH : Pseudo<(ops CRRC:$crS, u16imm:$opc,
target:$true, target:$false),
"; COND_BRANCH", []>;
"bnu $crS, $block", BrB>;
}
-let isCall = 1, noResults = 1,
+let isCall = 1, noResults = 1, PPC970_Unit = 7,
// All calls clobber the non-callee saved registers...
Defs = [R0,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,
F0,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12,F13,
// D-Form instructions. Most instructions that perform an operation on a
// register and an immediate are of this type.
//
-let isLoad = 1 in {
+let isLoad = 1, PPC970_Unit = 2 in {
def LBZ : DForm_1<34, (ops GPRC:$rD, memri:$src),
"lbz $rD, $src", LdStGeneral,
[(set GPRC:$rD, (zextload iaddr:$src, i8))]>;
"lwzu $rD, $disp($rA)", LdStGeneral,
[]>;
}
+let PPC970_Unit = 1 in { // FXU Operations.
def ADDI : DForm_2<14, (ops GPRC:$rD, GPRC:$rA, s16imm:$imm),
"addi $rD, $rA, $imm", IntGeneral,
[(set GPRC:$rD, (add GPRC:$rA, immSExt16:$imm))]>;
def LIS : DForm_2_r0<15, (ops GPRC:$rD, symbolHi:$imm),
"lis $rD, $imm", IntGeneral,
[(set GPRC:$rD, imm16Shifted:$imm)]>;
-let isStore = 1, noResults = 1 in {
+}
+let isStore = 1, noResults = 1, PPC970_Unit = 2 in {
def STMW : DForm_3<47, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
"stmw $rS, $disp($rA)", LdStLMW,
[]>;
"stwu $rS, $disp($rA)", LdStGeneral,
[]>;
}
+let PPC970_Unit = 1 in { // FXU Operations.
def ANDIo : DForm_4<28, (ops GPRC:$dst, GPRC:$src1, u16imm:$src2),
"andi. $dst, $src1, $src2", IntGeneral,
[(set GPRC:$dst, (and GPRC:$src1, immZExt16:$src2))]>,
"cmplwi $dst, $src1, $src2", IntCompare>;
def CMPLDI : DForm_6_ext<10, (ops CRRC:$dst, GPRC:$src1, u16imm:$src2),
"cmpldi $dst, $src1, $src2", IntCompare>, isPPC64;
-let isLoad = 1 in {
+}
+let isLoad = 1, PPC970_Unit = 2 in {
def LFS : DForm_8<48, (ops F4RC:$rD, memri:$src),
"lfs $rD, $src", LdStLFDU,
[(set F4RC:$rD, (load iaddr:$src))]>;
"lfd $rD, $src", LdStLFD,
[(set F8RC:$rD, (load iaddr:$src))]>;
}
-let isStore = 1, noResults = 1 in {
+let isStore = 1, noResults = 1, PPC970_Unit = 2 in {
def STFS : DForm_9<52, (ops F4RC:$rS, memri:$dst),
"stfs $rS, $dst", LdStUX,
[(store F4RC:$rS, iaddr:$dst)]>;
// DS-Form instructions. Load/Store instructions available in PPC-64
//
-let isLoad = 1 in {
+let isLoad = 1, PPC970_Unit = 2 in {
def LWA : DSForm_1<58, 2, (ops GPRC:$rT, s16immX4:$DS, GPRC:$rA),
"lwa $rT, $DS($rA)", LdStLWA,
[]>, isPPC64;
"ld $rT, $DS($rA)", LdStLD,
[]>, isPPC64;
}
-let isStore = 1, noResults = 1 in {
+let isStore = 1, noResults = 1, PPC970_Unit = 2 in {
def STD : DSForm_2<62, 0, (ops GPRC:$rT, s16immX4:$DS, GPRC:$rA),
"std $rT, $DS($rA)", LdStSTD,
[]>, isPPC64;
// X-Form instructions. Most instructions that perform an operation on a
// register and another register are of this type.
//
-let isLoad = 1 in {
+let isLoad = 1, PPC970_Unit = 2 in {
def LBZX : XForm_1<31, 87, (ops GPRC:$rD, memrr:$src),
"lbzx $rD, $src", LdStGeneral,
[(set GPRC:$rD, (zextload xaddr:$src, i8))]>;
}
def LVSL : XForm_1<31, 6, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
"lvsl $vD, $base, $rA", LdStGeneral,
- []>;
+ []>, PPC970_Unit_LSU;
def LVSR : XForm_1<31, 38, (ops VRRC:$vD, GPRC:$base, GPRC:$rA),
"lvsl $vD, $base, $rA", LdStGeneral,
- []>;
+ []>, PPC970_Unit_LSU;
+let PPC970_Unit = 1 in { // FXU Operations.
def NAND : XForm_6<31, 476, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"nand $rA, $rS, $rB", IntGeneral,
[(set GPRC:$rA, (not (and GPRC:$rS, GPRC:$rB)))]>;
def SRAW : XForm_6<31, 792, (ops GPRC:$rA, GPRC:$rS, GPRC:$rB),
"sraw $rA, $rS, $rB", IntShift,
[(set GPRC:$rA, (PPCsra GPRC:$rS, GPRC:$rB))]>;
-let isStore = 1, noResults = 1 in {
+}
+let isStore = 1, noResults = 1, PPC970_Unit = 2 in {
def STBX : XForm_8<31, 215, (ops GPRC:$rS, memrr:$dst),
"stbx $rS, $dst", LdStGeneral,
[(truncstore GPRC:$rS, xaddr:$dst, i8)]>;
"stvx $rS, $dst", LdStGeneral,
[(store (v4f32 VRRC:$rS), xoaddr:$dst)]>;
}
+let PPC970_Unit = 1 in { // FXU Operations.
def SRAWI : XForm_10<31, 824, (ops GPRC:$rA, GPRC:$rS, u5imm:$SH),
"srawi $rA, $rS, $SH", IntShift,
[(set GPRC:$rA, (sra GPRC:$rS, (i32 imm:$SH)))]>;
"cmplw $crD, $rA, $rB", IntCompare>;
def CMPLD : XForm_16_ext<31, 32, (ops CRRC:$crD, GPRC:$rA, GPRC:$rB),
"cmpld $crD, $rA, $rB", IntCompare>, isPPC64;
+}
+let PPC970_Unit = 3 in { // FPU Operations.
//def FCMPO : XForm_17<63, 32, (ops CRRC:$crD, FPRC:$fA, FPRC:$fB),
// "fcmpo $crD, $fA, $fB", FPCompare>;
def FCMPUS : XForm_17<63, 0, (ops CRRC:$crD, F4RC:$fA, F4RC:$fB),
"fcmpu $crD, $fA, $fB", FPCompare>;
def FCMPUD : XForm_17<63, 0, (ops CRRC:$crD, F8RC:$fA, F8RC:$fB),
"fcmpu $crD, $fA, $fB", FPCompare>;
-
-let isLoad = 1 in {
+}
+let isLoad = 1, PPC970_Unit = 2 in {
def LFSX : XForm_25<31, 535, (ops F4RC:$frD, memrr:$src),
"lfsx $frD, $src", LdStLFDU,
[(set F4RC:$frD, (load xaddr:$src))]>;
"lfdx $frD, $src", LdStLFDU,
[(set F8RC:$frD, (load xaddr:$src))]>;
}
+let PPC970_Unit = 3 in { // FPU Operations.
def FCFID : XForm_26<63, 846, (ops F8RC:$frD, F8RC:$frB),
"fcfid $frD, $frB", FPGeneral,
[(set F8RC:$frD, (PPCfcfid F8RC:$frB))]>, isPPC64;
def FSQRTS : XForm_26<59, 22, (ops F4RC:$frD, F4RC:$frB),
"fsqrts $frD, $frB", FPSqrt,
[(set F4RC:$frD, (fsqrt F4RC:$frB))]>;
+}
/// FMR is split into 3 versions, one for 4/8 byte FP, and one for extending.
+///
+/// Note that these are defined as pseudo-ops on the PPC970 because they are
+/// often coallesced away and we don't want the dispatch group builder to think
+/// that they will fill slots (which could cause the load of a LSU reject to
+/// sneak into a d-group with a store).
def FMRS : XForm_26<63, 72, (ops F4RC:$frD, F4RC:$frB),
"fmr $frD, $frB", FPGeneral,
- []>; // (set F4RC:$frD, F4RC:$frB)
+ []>, // (set F4RC:$frD, F4RC:$frB)
+ PPC970_Unit_Pseudo;
def FMRD : XForm_26<63, 72, (ops F8RC:$frD, F8RC:$frB),
"fmr $frD, $frB", FPGeneral,
- []>; // (set F8RC:$frD, F8RC:$frB)
+ []>, // (set F8RC:$frD, F8RC:$frB)
+ PPC970_Unit_Pseudo;
def FMRSD : XForm_26<63, 72, (ops F8RC:$frD, F4RC:$frB),
"fmr $frD, $frB", FPGeneral,
- [(set F8RC:$frD, (fextend F4RC:$frB))]>;
+ [(set F8RC:$frD, (fextend F4RC:$frB))]>,
+ PPC970_Unit_Pseudo;
+let PPC970_Unit = 3 in { // FPU Operations.
// These are artificially split into two different forms, for 4/8 byte FP.
def FABSS : XForm_26<63, 264, (ops F4RC:$frD, F4RC:$frB),
"fabs $frD, $frB", FPGeneral,
def FNEGD : XForm_26<63, 40, (ops F8RC:$frD, F8RC:$frB),
"fneg $frD, $frB", FPGeneral,
[(set F8RC:$frD, (fneg F8RC:$frB))]>;
+}
-
-let isStore = 1, noResults = 1 in {
+let isStore = 1, noResults = 1, PPC970_Unit = 2 in {
def STFIWX: XForm_28<31, 983, (ops F8RC:$frS, memrr:$dst),
"stfiwx $frS, $dst", LdStUX,
[(PPCstfiwx F8RC:$frS, xoaddr:$dst)]>;
// XL-Form instructions. condition register logical ops.
//
def MCRF : XLForm_3<19, 0, (ops CRRC:$BF, CRRC:$BFA),
- "mcrf $BF, $BFA", BrMCR>;
+ "mcrf $BF, $BFA", BrMCR>,
+ PPC970_DGroup_First, PPC970_Unit_CRU;
-// XFX-Form instructions. Instructions that deal with SPRs
+// XFX-Form instructions. Instructions that deal with SPRs.
//
-// Note that although LR should be listed as `8' and CTR as `9' in the SPR
-// field, the manual lists the groups of bits as [5-9] = 0, [0-4] = 8 or 9
-// which means the SPR value needs to be multiplied by a factor of 32.
-def MFCTR : XFXForm_1_ext<31, 339, 9, (ops GPRC:$rT), "mfctr $rT", SprMFSPR>;
-def MFLR : XFXForm_1_ext<31, 339, 8, (ops GPRC:$rT), "mflr $rT", SprMFSPR>;
-def MFCR : XFXForm_3<31, 19, (ops GPRC:$rT), "mfcr $rT", SprMFCR>;
+def MFCTR : XFXForm_1_ext<31, 339, 9, (ops GPRC:$rT), "mfctr $rT", SprMFSPR>,
+ PPC970_DGroup_First, PPC970_Unit_FXU;
+def MFLR : XFXForm_1_ext<31, 339, 8, (ops GPRC:$rT), "mflr $rT", SprMFSPR>,
+ PPC970_DGroup_First, PPC970_Unit_FXU;
+def MFCR : XFXForm_3<31, 19, (ops GPRC:$rT), "mfcr $rT", SprMFCR>,
+ PPC970_MicroCode, PPC970_Unit_CRU;
def MTCRF : XFXForm_5<31, 144, (ops crbitm:$FXM, GPRC:$rS),
- "mtcrf $FXM, $rS", BrMCRX>;
+ "mtcrf $FXM, $rS", BrMCRX>,
+ PPC970_MicroCode, PPC970_Unit_CRU;
def MFOCRF: XFXForm_5a<31, 19, (ops GPRC:$rT, crbitm:$FXM),
- "mfcr $rT, $FXM", SprMFCR>;
-def MTCTR : XFXForm_7_ext<31, 467, 9, (ops GPRC:$rS), "mtctr $rS", SprMTSPR>;
-def MTLR : XFXForm_7_ext<31, 467, 8, (ops GPRC:$rS), "mtlr $rS", SprMTSPR>;
+ "mfcr $rT, $FXM", SprMFCR>,
+ PPC970_DGroup_First, PPC970_Unit_CRU;
+def MTCTR : XFXForm_7_ext<31, 467, 9, (ops GPRC:$rS), "mtctr $rS", SprMTSPR>,
+ PPC970_DGroup_First, PPC970_Unit_FXU;
+def MTLR : XFXForm_7_ext<31, 467, 8, (ops GPRC:$rS), "mtlr $rS", SprMTSPR>,
+ PPC970_DGroup_First, PPC970_Unit_FXU;
def MTSPR : XFXForm_7<31, 467, (ops GPRC:$rS, u16imm:$UIMM), "mtspr $UIMM, $rS",
- SprMTSPR>;
+ SprMTSPR>,
+ PPC970_DGroup_Single, PPC970_Unit_FXU;
// XS-Form instructions. Just 'sradi'
//
+let PPC970_Unit = 1 in { // FXU Operations.
def SRADI : XSForm_1<31, 413, (ops GPRC:$rA, GPRC:$rS, u6imm:$SH),
"sradi $rA, $rS, $SH", IntRotateD>, isPPC64;
[(set GPRC:$rT, (adde GPRC:$rA, GPRC:$rB))]>;
def DIVD : XOForm_1<31, 489, 0, (ops G8RC:$rT, G8RC:$rA, G8RC:$rB),
"divd $rT, $rA, $rB", IntDivD,
- [(set G8RC:$rT, (sdiv G8RC:$rA, G8RC:$rB))]>, isPPC64;
+ [(set G8RC:$rT, (sdiv G8RC:$rA, G8RC:$rB))]>, isPPC64,
+ PPC970_DGroup_First;
def DIVDU : XOForm_1<31, 457, 0, (ops G8RC:$rT, G8RC:$rA, G8RC:$rB),
"divdu $rT, $rA, $rB", IntDivD,
- [(set G8RC:$rT, (udiv G8RC:$rA, G8RC:$rB))]>, isPPC64;
+ [(set G8RC:$rT, (udiv G8RC:$rA, G8RC:$rB))]>, isPPC64,
+ PPC970_DGroup_First;
def DIVW : XOForm_1<31, 491, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"divw $rT, $rA, $rB", IntDivW,
- [(set GPRC:$rT, (sdiv GPRC:$rA, GPRC:$rB))]>;
+ [(set GPRC:$rT, (sdiv GPRC:$rA, GPRC:$rB))]>,
+ PPC970_DGroup_First;
def DIVWU : XOForm_1<31, 459, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
"divwu $rT, $rA, $rB", IntDivW,
- [(set GPRC:$rT, (udiv GPRC:$rA, GPRC:$rB))]>;
+ [(set GPRC:$rT, (udiv GPRC:$rA, GPRC:$rB))]>,
+ PPC970_DGroup_First;
def MULHD : XOForm_1<31, 73, 0, (ops G8RC:$rT, G8RC:$rA, G8RC:$rB),
"mulhd $rT, $rA, $rB", IntMulHW,
[(set G8RC:$rT, (mulhs G8RC:$rA, G8RC:$rB))]>;
def SUBFZE : XOForm_3<31, 200, 0, (ops GPRC:$rT, GPRC:$rA),
"subfze $rT, $rA", IntGeneral,
[(set GPRC:$rT, (sube 0, GPRC:$rA))]>;
+}
// A-Form instructions. Most of the instructions executed in the FPU are of
// this type.
//
+let PPC970_Unit = 3 in { // FPU Operations.
def FMADD : AForm_1<63, 29,
(ops F8RC:$FRT, F8RC:$FRA, F8RC:$FRC, F8RC:$FRB),
"fmadd $FRT, $FRA, $FRC, $FRB", FPFused,
(ops F4RC:$FRT, F4RC:$FRA, F4RC:$FRB),
"fsubs $FRT, $FRA, $FRB", FPGeneral,
[(set F4RC:$FRT, (fsub F4RC:$FRA, F4RC:$FRB))]>;
+}
+let PPC970_Unit = 1 in { // FXU Operations.
// M-Form instructions. rotate and mask instructions.
//
let isTwoAddress = 1, isCommutable = 1 in {
(ops G8RC:$rA, G8RC:$rS, u6imm:$SH, u6imm:$ME),
"rldicr $rA, $rS, $SH, $ME", IntRotateD,
[]>, isPPC64;
+}
+let PPC970_Unit = 5 in { // VALU Operations.
// VA-Form instructions. 3-input AltiVec ops.
def VMADDFP : VAForm_1<46, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB, VRRC:$vC),
"vmaddfp $vD, $vA, $vC, $vB", VecFP,
def V_SET0 : VXForm_setzero<1220, (ops VRRC:$vD),
"vxor $vD, $vD, $vD", VecFP,
[]>;
-
+}
//===----------------------------------------------------------------------===//
// DWARF Pseudo Instructions
(XORIS GPRC:$tmp, (HI16 imm:$imm))]>;
*/
-//===----------------------------------------------------------------------===//
-// PowerPCInstrInfo Definition
-//
-def PowerPCInstrInfo : InstrInfo {
- let TSFlagsFields = [ "VMX", "PPC64" ];
- let TSFlagsShifts = [ 0, 1 ];
-
- let isLittleEndianEncoding = 1;
-}
-