//===- SPUInstrInfo.cpp - Cell SPU Instruction Information ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file was developed by a team from the Computer Systems Research // Department at The Aerospace Corporation. // // See README.txt for details. // //===----------------------------------------------------------------------===// // // This file contains the Cell SPU implementation of the TargetInstrInfo class. // //===----------------------------------------------------------------------===// #include "SPURegisterNames.h" #include "SPUInstrInfo.h" #include "SPUTargetMachine.h" #include "SPUGenInstrInfo.inc" #include "llvm/CodeGen/MachineInstrBuilder.h" #include using namespace llvm; SPUInstrInfo::SPUInstrInfo(SPUTargetMachine &tm) : TargetInstrInfo(SPUInsts, sizeof(SPUInsts)/sizeof(SPUInsts[0])), TM(tm), RI(*TM.getSubtargetImpl(), *this) { /* NOP */ } /// getPointerRegClass - Return the register class to use to hold pointers. /// This is used for addressing modes. const TargetRegisterClass * SPUInstrInfo::getPointerRegClass() const { return &SPU::R32CRegClass; } bool SPUInstrInfo::isMoveInstr(const MachineInstr& MI, unsigned& sourceReg, unsigned& destReg) const { // Primarily, ORI and OR are generated by copyRegToReg. But, there are other // cases where we can safely say that what's being done is really a move // (see how PowerPC does this -- it's the model for this code too.) switch (MI.getOpcode()) { default: break; case SPU::ORIv4i32: case SPU::ORIr32: case SPU::ORIf64: case SPU::ORIf32: case SPU::ORIr64: case SPU::ORHIv8i16: case SPU::ORHIr16: // case SPU::ORHI1To2: case SPU::ORBIv16i8: //case SPU::ORBIr8: case SPU::ORI2To4: // case SPU::ORI1To4: case SPU::AHIvec: case SPU::AHIr16: case SPU::AIvec: case SPU::AIr32: assert(MI.getNumOperands() == 3 && MI.getOperand(0).isRegister() && MI.getOperand(1).isRegister() && MI.getOperand(2).isImmediate() && "invalid SPU ORI/ORHI/ORBI/AHI/AI/SFI/SFHI instruction!"); if (MI.getOperand(2).getImmedValue() == 0) { sourceReg = MI.getOperand(1).getReg(); destReg = MI.getOperand(0).getReg(); return true; } break; #if 0 case SPU::ORIf64: case SPU::ORIf32: // Special case because there's no third immediate operand to the // instruction (the constant is embedded in the instruction) assert(MI.getOperand(0).isRegister() && MI.getOperand(1).isRegister() && "ORIf32/f64: operands not registers"); sourceReg = MI.getOperand(1).getReg(); destReg = MI.getOperand(0).getReg(); return true; #endif // case SPU::ORv16i8_i8: case SPU::ORv8i16_i16: case SPU::ORv4i32_i32: case SPU::ORv2i64_i64: case SPU::ORv4f32_f32: case SPU::ORv2f64_f64: // case SPU::ORi8_v16i8: case SPU::ORi16_v8i16: case SPU::ORi32_v4i32: case SPU::ORi64_v2i64: case SPU::ORf32_v4f32: case SPU::ORf64_v2f64: case SPU::ORv16i8: case SPU::ORv8i16: case SPU::ORv4i32: case SPU::ORr32: case SPU::ORr64: case SPU::ORgprc: assert(MI.getNumOperands() == 3 && MI.getOperand(0).isRegister() && MI.getOperand(1).isRegister() && MI.getOperand(2).isRegister() && "invalid SPU OR(vec|r32|r64|gprc) instruction!"); if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) { sourceReg = MI.getOperand(1).getReg(); destReg = MI.getOperand(0).getReg(); return true; } break; } return false; } unsigned SPUInstrInfo::isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const { switch (MI->getOpcode()) { default: break; case SPU::LQDv16i8: case SPU::LQDv8i16: case SPU::LQDv4i32: case SPU::LQDv4f32: case SPU::LQDv2f64: case SPU::LQDr128: case SPU::LQDr64: case SPU::LQDr32: case SPU::LQDr16: case SPU::LQXv4i32: case SPU::LQXr128: case SPU::LQXr64: case SPU::LQXr32: case SPU::LQXr16: if (MI->getOperand(1).isImmediate() && !MI->getOperand(1).getImmedValue() && MI->getOperand(2).isFrameIndex()) { FrameIndex = MI->getOperand(2).getFrameIndex(); return MI->getOperand(0).getReg(); } break; } return 0; } unsigned SPUInstrInfo::isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const { switch (MI->getOpcode()) { default: break; case SPU::STQDv16i8: case SPU::STQDv8i16: case SPU::STQDv4i32: case SPU::STQDv4f32: case SPU::STQDv2f64: case SPU::STQDr128: case SPU::STQDr64: case SPU::STQDr32: case SPU::STQDr16: // case SPU::STQDr8: case SPU::STQXv16i8: case SPU::STQXv8i16: case SPU::STQXv4i32: case SPU::STQXv4f32: case SPU::STQXv2f64: case SPU::STQXr128: case SPU::STQXr64: case SPU::STQXr32: case SPU::STQXr16: // case SPU::STQXr8: if (MI->getOperand(1).isImmediate() && !MI->getOperand(1).getImmedValue() && MI->getOperand(2).isFrameIndex()) { FrameIndex = MI->getOperand(2).getFrameIndex(); return MI->getOperand(0).getReg(); } break; } return 0; }