#include "SPURegisterNames.h"
#include "SPUInstrInfo.h"
+#include "SPUInstrBuilder.h"
#include "SPUTargetMachine.h"
#include "SPUGenInstrInfo.inc"
#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include <iostream>
+#include "llvm/Support/Streams.h"
using namespace llvm;
break;
case SPU::ORIv4i32:
case SPU::ORIr32:
- case SPU::ORIr64:
case SPU::ORHIv8i16:
case SPU::ORHIr16:
- case SPU::ORHI1To2:
+ case SPU::ORHIi8i16:
case SPU::ORBIv16i8:
case SPU::ORBIr8:
- case SPU::ORI2To4:
- case SPU::ORI1To4:
+ case SPU::ORIi16i32:
+ case SPU::ORIi8i32:
case SPU::AHIvec:
case SPU::AHIr16:
case SPU::AIvec:
case SPU::ORr64:
case SPU::ORf32:
case SPU::ORf64:
- case SPU::ORgprc:
assert(MI.getNumOperands() == 3 &&
MI.getOperand(0).isRegister() &&
MI.getOperand(1).isRegister() &&
const TargetRegisterClass *DestRC,
const TargetRegisterClass *SrcRC) const
{
- if (DestRC != SrcRC) {
- cerr << "SPURegisterInfo::copyRegToReg(): DestRC != SrcRC not supported!\n";
- abort();
- }
+ // We support cross register class moves for our aliases, such as R3 in any
+ // reg class to any other reg class containing R3. This is required because
+ // we instruction select bitconvert i64 -> f64 as a noop for example, so our
+ // types have no specific meaning.
+
+ //if (DestRC != SrcRC) {
+ // cerr << "SPUInstrInfo::copyRegToReg(): DestRC != SrcRC not supported!\n";
+ // abort();
+ //}
if (DestRC == SPU::R8CRegisterClass) {
BuildMI(MBB, MI, get(SPU::ORBIr8), DestReg).addReg(SrcReg).addImm(0);
BuildMI(MBB, MI, get(SPU::ORf32), DestReg).addReg(SrcReg)
.addReg(SrcReg);
} else if (DestRC == SPU::R64CRegisterClass) {
- BuildMI(MBB, MI, get(SPU::ORIr64), DestReg).addReg(SrcReg).addImm(0);
+ BuildMI(MBB, MI, get(SPU::ORr64), DestReg).addReg(SrcReg)
+ .addReg(SrcReg);
} else if (DestRC == SPU::R64FPRegisterClass) {
BuildMI(MBB, MI, get(SPU::ORf64), DestReg).addReg(SrcReg)
.addReg(SrcReg);
- } else if (DestRC == SPU::GPRCRegisterClass) {
+ } /* else if (DestRC == SPU::GPRCRegisterClass) {
BuildMI(MBB, MI, get(SPU::ORgprc), DestReg).addReg(SrcReg)
.addReg(SrcReg);
- } else if (DestRC == SPU::VECREGRegisterClass) {
+ } */ else if (DestRC == SPU::VECREGRegisterClass) {
BuildMI(MBB, MI, get(SPU::ORv4i32), DestReg).addReg(SrcReg)
.addReg(SrcReg);
} else {
- std::cerr << "Attempt to copy unknown/unsupported register class!\n";
+ cerr << "Attempt to copy unknown/unsupported register class!\n";
abort();
}
}
+
+void
+SPUInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned SrcReg, bool isKill, int FrameIdx,
+ const TargetRegisterClass *RC) const
+{
+ unsigned opc;
+ if (RC == SPU::GPRCRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
+ ? SPU::STQDr128
+ : SPU::STQXr128;
+ } else if (RC == SPU::R64CRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
+ ? SPU::STQDr64
+ : SPU::STQXr64;
+ } else if (RC == SPU::R64FPRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
+ ? SPU::STQDr64
+ : SPU::STQXr64;
+ } else if (RC == SPU::R32CRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
+ ? SPU::STQDr32
+ : SPU::STQXr32;
+ } else if (RC == SPU::R32FPRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
+ ? SPU::STQDr32
+ : SPU::STQXr32;
+ } else if (RC == SPU::R16CRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) ?
+ SPU::STQDr16
+ : SPU::STQXr16;
+ } else {
+ assert(0 && "Unknown regclass!");
+ abort();
+ }
+
+ addFrameReference(BuildMI(MBB, MI, get(opc))
+ .addReg(SrcReg, false, false, isKill), FrameIdx);
+}
+
+void SPUInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
+ bool isKill,
+ SmallVectorImpl<MachineOperand> &Addr,
+ const TargetRegisterClass *RC,
+ SmallVectorImpl<MachineInstr*> &NewMIs) const {
+ cerr << "storeRegToAddr() invoked!\n";
+ abort();
+
+ if (Addr[0].isFrameIndex()) {
+ /* do what storeRegToStackSlot does here */
+ } else {
+ unsigned Opc = 0;
+ if (RC == SPU::GPRCRegisterClass) {
+ /* Opc = PPC::STW; */
+ } else if (RC == SPU::R16CRegisterClass) {
+ /* Opc = PPC::STD; */
+ } else if (RC == SPU::R32CRegisterClass) {
+ /* Opc = PPC::STFD; */
+ } else if (RC == SPU::R32FPRegisterClass) {
+ /* Opc = PPC::STFD; */
+ } else if (RC == SPU::R64FPRegisterClass) {
+ /* Opc = PPC::STFS; */
+ } else if (RC == SPU::VECREGRegisterClass) {
+ /* Opc = PPC::STVX; */
+ } else {
+ assert(0 && "Unknown regclass!");
+ abort();
+ }
+ MachineInstrBuilder MIB = BuildMI(get(Opc))
+ .addReg(SrcReg, false, false, isKill);
+ for (unsigned i = 0, e = Addr.size(); i != e; ++i) {
+ MachineOperand &MO = Addr[i];
+ if (MO.isRegister())
+ MIB.addReg(MO.getReg());
+ else if (MO.isImmediate())
+ MIB.addImm(MO.getImm());
+ else
+ MIB.addFrameIndex(MO.getIndex());
+ }
+ NewMIs.push_back(MIB);
+ }
+}
+
+void
+SPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned DestReg, int FrameIdx,
+ const TargetRegisterClass *RC) const
+{
+ unsigned opc;
+ if (RC == SPU::GPRCRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
+ ? SPU::LQDr128
+ : SPU::LQXr128;
+ } else if (RC == SPU::R64CRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
+ ? SPU::LQDr64
+ : SPU::LQXr64;
+ } else if (RC == SPU::R64FPRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
+ ? SPU::LQDr64
+ : SPU::LQXr64;
+ } else if (RC == SPU::R32CRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
+ ? SPU::LQDr32
+ : SPU::LQXr32;
+ } else if (RC == SPU::R32FPRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
+ ? SPU::LQDr32
+ : SPU::LQXr32;
+ } else if (RC == SPU::R16CRegisterClass) {
+ opc = (FrameIdx < SPUFrameInfo::maxFrameOffset())
+ ? SPU::LQDr16
+ : SPU::LQXr16;
+ } else {
+ assert(0 && "Unknown regclass in loadRegFromStackSlot!");
+ abort();
+ }
+
+ addFrameReference(BuildMI(MBB, MI, get(opc)).addReg(DestReg), FrameIdx);
+}
+
+/*!
+ \note We are really pessimistic here about what kind of a load we're doing.
+ */
+void SPUInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
+ SmallVectorImpl<MachineOperand> &Addr,
+ const TargetRegisterClass *RC,
+ SmallVectorImpl<MachineInstr*> &NewMIs)
+ const {
+ cerr << "loadRegToAddr() invoked!\n";
+ abort();
+
+ if (Addr[0].isFrameIndex()) {
+ /* do what loadRegFromStackSlot does here... */
+ } else {
+ unsigned Opc = 0;
+ if (RC == SPU::R8CRegisterClass) {
+ /* do brilliance here */
+ } else if (RC == SPU::R16CRegisterClass) {
+ /* Opc = PPC::LWZ; */
+ } else if (RC == SPU::R32CRegisterClass) {
+ /* Opc = PPC::LD; */
+ } else if (RC == SPU::R32FPRegisterClass) {
+ /* Opc = PPC::LFD; */
+ } else if (RC == SPU::R64FPRegisterClass) {
+ /* Opc = PPC::LFS; */
+ } else if (RC == SPU::VECREGRegisterClass) {
+ /* Opc = PPC::LVX; */
+ } else if (RC == SPU::GPRCRegisterClass) {
+ /* Opc = something else! */
+ } else {
+ assert(0 && "Unknown regclass!");
+ abort();
+ }
+ MachineInstrBuilder MIB = BuildMI(get(Opc), DestReg);
+ for (unsigned i = 0, e = Addr.size(); i != e; ++i) {
+ MachineOperand &MO = Addr[i];
+ if (MO.isRegister())
+ MIB.addReg(MO.getReg());
+ else if (MO.isImmediate())
+ MIB.addImm(MO.getImm());
+ else
+ MIB.addFrameIndex(MO.getIndex());
+ }
+ NewMIs.push_back(MIB);
+ }
+}
+
+/// foldMemoryOperand - SPU, like PPC, can only fold spills into
+/// copy instructions, turning them into load/store instructions.
+MachineInstr *
+SPUInstrInfo::foldMemoryOperand(MachineFunction &MF,
+ MachineInstr *MI,
+ SmallVectorImpl<unsigned> &Ops,
+ int FrameIndex) const
+{
+#if SOMEDAY_SCOTT_LOOKS_AT_ME_AGAIN
+ if (Ops.size() != 1) return NULL;
+
+ unsigned OpNum = Ops[0];
+ unsigned Opc = MI->getOpcode();
+ MachineInstr *NewMI = 0;
+
+ if ((Opc == SPU::ORr32
+ || Opc == SPU::ORv4i32)
+ && MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) {
+ if (OpNum == 0) { // move -> store
+ unsigned InReg = MI->getOperand(1).getReg();
+ if (FrameIndex < SPUFrameInfo::maxFrameOffset()) {
+ NewMI = addFrameReference(BuildMI(TII.get(SPU::STQDr32)).addReg(InReg),
+ FrameIndex);
+ }
+ } else { // move -> load
+ unsigned OutReg = MI->getOperand(0).getReg();
+ Opc = (FrameIndex < SPUFrameInfo::maxFrameOffset()) ? SPU::STQDr32 : SPU::STQXr32;
+ NewMI = addFrameReference(BuildMI(TII.get(Opc), OutReg), FrameIndex);
+ }
+ }
+
+ if (NewMI)
+ NewMI->copyKillDeadInfo(MI);
+
+ return NewMI;
+#else
+ return 0;
+#endif
+}
+