mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-17 21:35:07 +00:00
Several big changes:
1. Use flags on the instructions in the .td file to indicate the PPC970 unit type instead of a table in the .cpp file. Much cleaner. 2. Change the hazard recognizer to build d-groups according to the actual algorithm used, not my flawed understanding of it. 3. Model "must be in the first slot" and "must be the only instr in a group" accurately. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26719 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
fc3549ee8c
commit
88d211f823
@ -67,17 +67,32 @@ def : Processor<"g5", G5Itineraries,
|
||||
Feature64Bit /*, Feature64BitRegs */]>;
|
||||
|
||||
|
||||
def PPCInstrInfo : InstrInfo {
|
||||
// Define how we want to layout our TargetSpecific information field... This
|
||||
// should be kept up-to-date with the fields in the PPCInstrInfo.h file.
|
||||
let TSFlagsFields = ["PPC970_First",
|
||||
"PPC970_Single",
|
||||
"PPC970_Unit"];
|
||||
let TSFlagsShifts = [0,
|
||||
1,
|
||||
2];
|
||||
|
||||
let isLittleEndianEncoding = 1;
|
||||
}
|
||||
|
||||
|
||||
def PPC : Target {
|
||||
// Pointers on PPC are 32-bits in size.
|
||||
let PointerType = i32;
|
||||
|
||||
// Information about the instructions.
|
||||
let InstructionSet = PPCInstrInfo;
|
||||
|
||||
|
||||
// According to the Mach-O Runtime ABI, these regs are nonvolatile across
|
||||
// calls
|
||||
let CalleeSavedRegisters = [R1, R13, R14, R15, R16, R17, R18, R19,
|
||||
R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, F14, F15,
|
||||
F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29,
|
||||
F30, F31, CR2, CR3, CR4, LR];
|
||||
|
||||
// Pull in Instruction Info:
|
||||
let InstructionSet = PowerPCInstrInfo;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define DEBUG_TYPE "sched"
|
||||
#include "PPCHazardRecognizers.h"
|
||||
#include "PPC.h"
|
||||
#include "PPCInstrInfo.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include <iostream>
|
||||
using namespace llvm;
|
||||
@ -23,15 +24,14 @@ 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,
|
||||
@ -41,8 +41,6 @@ using namespace llvm;
|
||||
// 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.
|
||||
@ -50,103 +48,70 @@ using namespace llvm;
|
||||
// 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);
|
||||
|
||||
return FXU;
|
||||
isLoad = TID.Flags & M_LOAD_FLAG;
|
||||
isStore = TID.Flags & M_STORE_FLAG;
|
||||
|
||||
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;
|
||||
}
|
||||
@ -157,53 +122,76 @@ isLoadOfStoredAddress(unsigned LoadSize, SDOperand Ptr1, SDOperand Ptr2) const {
|
||||
/// 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,
|
||||
@ -215,41 +203,61 @@ getHazardType(SDNode *Node) {
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define PPCHAZRECS_H
|
||||
|
||||
#include "llvm/CodeGen/ScheduleDAG.h"
|
||||
#include "PPCInstrInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -25,16 +26,9 @@ namespace llvm {
|
||||
/// setting the CTR register then branching through it within a dispatch group),
|
||||
/// or storing then loading from the same address within a dispatch group.
|
||||
class PPCHazardRecognizer970 : public HazardRecognizer {
|
||||
unsigned NumIssued; // Number of insts issued, including advanced cycles.
|
||||
const TargetInstrInfo &TII;
|
||||
|
||||
// Number of various types of instructions in the current dispatch group.
|
||||
unsigned NumFXU; // Number of Fixed Point (integer) instructions
|
||||
unsigned NumLSU; // Number of Load/Store instructions
|
||||
unsigned NumFPU; // Number of Floating Point instructions
|
||||
bool HasCR; // True if Condition Register instruction issued
|
||||
bool HasSPR; // True if Special-Purpose Register instruction used
|
||||
bool HasVALU; // True if Vector Arithmetic instruction issued
|
||||
bool HasVPERM; // True if Vector Permute instruction issued
|
||||
unsigned NumIssued; // Number of insts issued, including advanced cycles.
|
||||
|
||||
// Various things that can cause a structural hazard.
|
||||
|
||||
@ -42,17 +36,17 @@ class PPCHazardRecognizer970 : public HazardRecognizer {
|
||||
bool HasCTRSet;
|
||||
|
||||
// StoredPtr - Keep track of the address of any store. If we see a load from
|
||||
// the same address (or one that aliases it), disallow the store. We only
|
||||
// need one pointer here, because there can only be two LSU operations and we
|
||||
// only get an LSU reject if the first is a store and the second is a load.
|
||||
// the same address (or one that aliases it), disallow the store. We can have
|
||||
// up to four stores in one dispatch group, hence we track up to 4.
|
||||
//
|
||||
// This is null if we haven't seen a store yet. We keep track of both
|
||||
// operands of the store here, since we support [r+r] and [r+i] addressing.
|
||||
SDOperand StorePtr1, StorePtr2;
|
||||
unsigned StoreSize;
|
||||
SDOperand StorePtr1[4], StorePtr2[4];
|
||||
unsigned StoreSize[4];
|
||||
unsigned NumStores;
|
||||
|
||||
public:
|
||||
PPCHazardRecognizer970();
|
||||
PPCHazardRecognizer970(const TargetInstrInfo &TII);
|
||||
virtual HazardType getHazardType(SDNode *Node);
|
||||
virtual void EmitInstruction(SDNode *Node);
|
||||
virtual void AdvanceCycle();
|
||||
@ -63,13 +57,11 @@ private:
|
||||
///
|
||||
void EndDispatchGroup();
|
||||
|
||||
enum PPC970InstrType {
|
||||
FXU, FXU_FIRST, LSU_LD, LSU_ST, FPU, CR, SPR, VALU, VPERM, BR, PseudoInst
|
||||
};
|
||||
|
||||
/// GetInstrType - Classify the specified powerpc opcode according to its
|
||||
/// pipeline.
|
||||
PPC970InstrType GetInstrType(unsigned Opcode);
|
||||
PPCII::PPC970_Unit GetInstrType(unsigned Opcode,
|
||||
bool &isFirst, bool &isSingle,
|
||||
bool &isLoad, bool &isStore);
|
||||
|
||||
bool isLoadOfStoredAddress(unsigned LoadSize,
|
||||
SDOperand Ptr1, SDOperand Ptr2) const;
|
||||
|
@ -129,7 +129,9 @@ namespace {
|
||||
virtual HazardRecognizer *CreateTargetHazardRecognizer() {
|
||||
// Should use subtarget info to pick the right hazard recognizer. For
|
||||
// now, always return a PPC970 recognizer.
|
||||
return new PPCHazardRecognizer970();
|
||||
const TargetInstrInfo *II = PPCLowering.getTargetMachine().getInstrInfo();
|
||||
assert(II && "No InstrInfo?");
|
||||
return new PPCHazardRecognizer970(*II);
|
||||
}
|
||||
|
||||
// Include the pieces autogenerated from the target description.
|
||||
|
@ -27,8 +27,28 @@ class I<bits<6> opcode, dag OL, string asmstr, InstrItinClass itin>
|
||||
let OperandList = OL;
|
||||
let AsmString = asmstr;
|
||||
let Itinerary = itin;
|
||||
|
||||
/// These fields correspond to the fields in PPCInstrInfo.h. Any changes to
|
||||
/// these must be reflected there! See comments there for what these are.
|
||||
bits<1> PPC970_First = 0;
|
||||
bits<1> PPC970_Single = 0;
|
||||
bits<3> PPC970_Unit = 0;
|
||||
}
|
||||
|
||||
class PPC970_DGroup_First { bits<1> PPC970_First = 1; }
|
||||
class PPC970_DGroup_Single { bits<1> PPC970_Single = 1; }
|
||||
class PPC970_MicroCode;
|
||||
|
||||
class PPC970_Unit_Pseudo { bits<3> PPC970_Unit = 0; }
|
||||
class PPC970_Unit_FXU { bits<3> PPC970_Unit = 1; }
|
||||
class PPC970_Unit_LSU { bits<3> PPC970_Unit = 2; }
|
||||
class PPC970_Unit_FPU { bits<3> PPC970_Unit = 3; }
|
||||
class PPC970_Unit_CRU { bits<3> PPC970_Unit = 4; }
|
||||
class PPC970_Unit_VALU { bits<3> PPC970_Unit = 5; }
|
||||
class PPC970_Unit_VPERM { bits<3> PPC970_Unit = 6; }
|
||||
class PPC970_Unit_BRU { bits<3> PPC970_Unit = 7; }
|
||||
|
||||
|
||||
// 1.7.1 I-Form
|
||||
class IForm<bits<6> opcode, bit aa, bit lk, dag OL, string asmstr,
|
||||
InstrItinClass itin, list<dag> pattern>
|
||||
|
@ -19,6 +19,43 @@
|
||||
#include "PPCRegisterInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// PPCII - This namespace holds all of the PowerPC target-specific
|
||||
/// per-instruction flags. These must match the corresponding definitions in
|
||||
/// PPC.td and PPCInstrFormats.td.
|
||||
namespace PPCII {
|
||||
enum {
|
||||
// PPC970 Instruction Flags. These flags describe the characteristics of the
|
||||
// PowerPC 970 (aka G5) dispatch groups and how they are formed out of
|
||||
// raw machine instructions.
|
||||
|
||||
/// PPC970_First - This instruction starts a new dispatch group, so it will
|
||||
/// always be the first one in the group.
|
||||
PPC970_First = 0x1,
|
||||
|
||||
/// PPC970_Single - This instruction starts a new dispatch group and
|
||||
/// terminates it, so it will be the sole instruction in the group.
|
||||
PPC970_Single = 0x2,
|
||||
|
||||
/// PPC970_Mask/Shift - This is a bitmask that selects the pipeline type that
|
||||
/// an instruction is issued to.
|
||||
PPC970_Shift = 2,
|
||||
PPC970_Mask = 0x07 << PPC970_Shift,
|
||||
};
|
||||
enum PPC970_Unit {
|
||||
/// These are the various PPC970 execution unit pipelines. Each instruction
|
||||
/// is one of these.
|
||||
PPC970_Pseudo = 0 << PPC970_Shift, // Pseudo instruction
|
||||
PPC970_FXU = 1 << PPC970_Shift, // Fixed Point (aka Integer/ALU) Unit
|
||||
PPC970_LSU = 2 << PPC970_Shift, // Load Store Unit
|
||||
PPC970_FPU = 3 << PPC970_Shift, // Floating Point Unit
|
||||
PPC970_CRU = 4 << PPC970_Shift, // Control Register Unit
|
||||
PPC970_VALU = 5 << PPC970_Shift, // Vector ALU
|
||||
PPC970_VPERM = 6 << PPC970_Shift, // Vector Permute Unit
|
||||
PPC970_BRU = 7 << PPC970_Shift, // Branch Unit
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
class PPCInstrInfo : public TargetInstrInfo {
|
||||
const PPCRegisterInfo RI;
|
||||
|
@ -203,7 +203,7 @@ def FPContractions : Predicate<"!NoExcessFPPrecision">;
|
||||
|
||||
// Pseudo-instructions:
|
||||
|
||||
let isLoad = 1, hasCtrlDep = 1 in {
|
||||
let hasCtrlDep = 1 in {
|
||||
def ADJCALLSTACKDOWN : Pseudo<(ops u16imm:$amt),
|
||||
"; ADJCALLSTACKDOWN",
|
||||
[(callseq_start imm:$amt)]>;
|
||||
@ -220,7 +220,8 @@ def IMPLICIT_DEF_F4 : Pseudo<(ops F4RC:$rD), "; %rD = IMPLICIT_DEF_F4",
|
||||
|
||||
// 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,
|
||||
@ -229,16 +230,18 @@ let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler.
|
||||
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", []>;
|
||||
@ -266,7 +269,7 @@ let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, noResults = 1 in {
|
||||
"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,
|
||||
@ -284,7 +287,7 @@ let isCall = 1, noResults = 1,
|
||||
// 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))]>;
|
||||
@ -304,6 +307,7 @@ def LWZU : DForm_1<35, (ops GPRC:$rD, s16imm:$disp, GPRC:$rA),
|
||||
"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))]>;
|
||||
@ -332,7 +336,8 @@ def LI : DForm_2_r0<14, (ops GPRC:$rD, symbolLo:$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,
|
||||
[]>;
|
||||
@ -349,6 +354,7 @@ def STWU : DForm_3<37, (ops GPRC:$rS, s16imm:$disp, GPRC:$rA),
|
||||
"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))]>,
|
||||
@ -383,7 +389,8 @@ def CMPLWI : DForm_6_ext<10, (ops CRRC:$dst, GPRC:$src1, u16imm:$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))]>;
|
||||
@ -391,7 +398,7 @@ def LFD : DForm_8<50, (ops F8RC:$rD, memri:$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)]>;
|
||||
@ -402,7 +409,7 @@ def STFD : DForm_9<54, (ops F8RC:$rS, memri:$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;
|
||||
@ -410,7 +417,7 @@ def LD : DSForm_2<58, 0, (ops GPRC:$rT, s16immX4:$DS, GPRC:$rA),
|
||||
"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;
|
||||
@ -422,7 +429,7 @@ def STDU : DSForm_2<62, 1, (ops GPRC:$rT, s16immX4:$DS, GPRC:$rA),
|
||||
// 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))]>;
|
||||
@ -456,10 +463,11 @@ def LVX : XForm_1<31, 103, (ops VRRC:$vD, memrr:$src),
|
||||
}
|
||||
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)))]>;
|
||||
@ -517,7 +525,8 @@ def SRAD : XForm_6<31, 794, (ops G8RC:$rA, G8RC:$rS, G8RC:$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)]>;
|
||||
@ -549,6 +558,7 @@ def STVX : XForm_8<31, 231, (ops VRRC:$rS, memrr:$dst),
|
||||
"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)))]>;
|
||||
@ -576,14 +586,16 @@ def CMPLW : XForm_16_ext<31, 32, (ops CRRC:$crD, GPRC:$rA, GPRC:$rB),
|
||||
"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))]>;
|
||||
@ -591,6 +603,7 @@ def LFDX : XForm_25<31, 599, (ops F8RC:$frD, memrr:$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;
|
||||
@ -609,18 +622,28 @@ def FSQRT : XForm_26<63, 22, (ops F8RC:$frD, F8RC:$frB),
|
||||
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,
|
||||
@ -640,9 +663,9 @@ def FNEGS : XForm_26<63, 40, (ops F4RC:$frD, F4RC:$frB),
|
||||
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)]>;
|
||||
@ -657,27 +680,34 @@ def STFDX : XForm_28<31, 727, (ops F8RC:$frS, memrr:$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;
|
||||
|
||||
@ -697,16 +727,20 @@ def ADDE : XOForm_1<31, 138, 0, (ops GPRC:$rT, GPRC:$rA, GPRC:$rB),
|
||||
[(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))]>;
|
||||
@ -749,10 +783,12 @@ def SUBFME : XOForm_3<31, 232, 0, (ops GPRC:$rT, GPRC:$rA),
|
||||
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,
|
||||
@ -845,7 +881,9 @@ def FSUBS : AForm_2<59, 20,
|
||||
(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 {
|
||||
@ -882,7 +920,9 @@ def RLDICR : MDForm_1<30, 1,
|
||||
(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,
|
||||
@ -957,7 +997,7 @@ def VXOR : VXForm_1<1220, (ops VRRC:$vD, VRRC:$vA, VRRC:$vB),
|
||||
def V_SET0 : VXForm_setzero<1220, (ops VRRC:$vD),
|
||||
"vxor $vD, $vD, $vD", VecFP,
|
||||
[]>;
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DWARF Pseudo Instructions
|
||||
@ -1097,13 +1137,3 @@ def : Pattern<(xor GPRC:$in, imm:$imm),
|
||||
(XORIS GPRC:$tmp, (HI16 imm:$imm))]>;
|
||||
*/
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PowerPCInstrInfo Definition
|
||||
//
|
||||
def PowerPCInstrInfo : InstrInfo {
|
||||
let TSFlagsFields = [ "VMX", "PPC64" ];
|
||||
let TSFlagsShifts = [ 0, 1 ];
|
||||
|
||||
let isLittleEndianEncoding = 1;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user