diff options
Diffstat (limited to 'lib/Target/MBlaze')
34 files changed, 2087 insertions, 1105 deletions
diff --git a/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp b/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp index 4fc3b65..524f33d 100644 --- a/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp +++ b/lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp @@ -41,11 +41,13 @@ class MBlazeAsmParser : public TargetAsmParser { bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } MBlazeOperand *ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands); - MBlazeOperand *ParseRegister(); + MBlazeOperand *ParseRegister(unsigned &RegNo); MBlazeOperand *ParseImmediate(); MBlazeOperand *ParseFsl(); MBlazeOperand* ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands); + virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); + bool ParseDirectiveWord(unsigned Size, SMLoc L); bool MatchAndEmitInstruction(SMLoc IDLoc, @@ -332,6 +334,8 @@ MatchAndEmitInstruction(SMLoc IDLoc, return Error(IDLoc, "instruction use requires an option to be enabled"); case Match_MnemonicFail: return Error(IDLoc, "unrecognized instruction mnemonic"); + case Match_ConversionFail: + return Error(IDLoc, "unable to convert operands to instruction"); case Match_InvalidOperand: ErrorLoc = IDLoc; if (ErrorInfo != ~0U) { @@ -384,14 +388,19 @@ ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { return Op; } -MBlazeOperand *MBlazeAsmParser::ParseRegister() { +bool MBlazeAsmParser::ParseRegister(unsigned &RegNo, + SMLoc &StartLoc, SMLoc &EndLoc) { + return (ParseRegister(RegNo) == 0); +} + +MBlazeOperand *MBlazeAsmParser::ParseRegister(unsigned &RegNo) { SMLoc S = Parser.getTok().getLoc(); SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); switch (getLexer().getKind()) { default: return 0; case AsmToken::Identifier: - unsigned RegNo = MatchRegisterName(getLexer().getTok().getIdentifier()); + RegNo = MatchRegisterName(getLexer().getTok().getIdentifier()); if (RegNo == 0) return 0; @@ -400,7 +409,7 @@ MBlazeOperand *MBlazeAsmParser::ParseRegister() { } } -static unsigned MatchFslRegister(const StringRef &String) { +static unsigned MatchFslRegister(StringRef String) { if (!String.startswith("rfsl")) return -1; @@ -452,7 +461,8 @@ ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { MBlazeOperand *Op; // Attempt to parse the next token as a register name - Op = ParseRegister(); + unsigned RegNo; + Op = ParseRegister(RegNo); // Attempt to parse the next token as an FSL immediate if (!Op) diff --git a/lib/Target/MBlaze/CMakeLists.txt b/lib/Target/MBlaze/CMakeLists.txt index ee332a8..004057a 100644 --- a/lib/Target/MBlaze/CMakeLists.txt +++ b/lib/Target/MBlaze/CMakeLists.txt @@ -19,7 +19,7 @@ add_llvm_target(MBlazeCodeGen MBlazeInstrInfo.cpp MBlazeISelDAGToDAG.cpp MBlazeISelLowering.cpp - MBlazeFrameInfo.cpp + MBlazeFrameLowering.cpp MBlazeMCAsmInfo.cpp MBlazeRegisterInfo.cpp MBlazeSubtarget.cpp @@ -33,3 +33,8 @@ add_llvm_target(MBlazeCodeGen MBlazeELFWriterInfo.cpp MBlazeMCCodeEmitter.cpp ) + +add_subdirectory(AsmParser) +add_subdirectory(Disassembler) +add_subdirectory(InstPrinter) +add_subdirectory(TargetInfo) diff --git a/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp b/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp index b2a2474..3379ac2 100644 --- a/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp +++ b/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp @@ -69,8 +69,7 @@ static unsigned getRB(uint32_t insn) { } static int64_t getRS(uint32_t insn) { - int16_t val = (insn & 0x3FFF); - return val; + return MBlazeRegisterInfo::getSpecialRegisterFromNumbering(insn&0x3FFF); } static int64_t getIMM(uint32_t insn) { @@ -606,12 +605,12 @@ bool MBlazeDisassembler::getInstruction(MCInst &instr, case MBlazeII::FRCS: instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateImm(getRS(insn))); + instr.addOperand(MCOperand::CreateReg(getRS(insn))); break; case MBlazeII::FCRCS: + instr.addOperand(MCOperand::CreateReg(getRS(insn))); instr.addOperand(MCOperand::CreateReg(getRA(insn))); - instr.addOperand(MCOperand::CreateImm(getRS(insn))); break; case MBlazeII::FCRCX: diff --git a/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp index 704f81c..a7fd287 100644 --- a/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp +++ b/lib/Target/MBlaze/InstPrinter/MBlazeInstPrinter.cpp @@ -56,7 +56,7 @@ void MBlazeInstPrinter::printUnsignedImm(const MCInst *MI, int OpNo, raw_ostream &O) { const MCOperand &MO = MI->getOperand(OpNo); if (MO.isImm()) - O << MO.getImm(); + O << (uint32_t)MO.getImm(); else printOperand(MI, OpNo, O, NULL); } diff --git a/lib/Target/MBlaze/MBlazeAsmBackend.cpp b/lib/Target/MBlaze/MBlazeAsmBackend.cpp index 944ebf1..a4b21af 100644 --- a/lib/Target/MBlaze/MBlazeAsmBackend.cpp +++ b/lib/Target/MBlaze/MBlazeAsmBackend.cpp @@ -9,14 +9,17 @@ #include "llvm/Target/TargetAsmBackend.h" #include "MBlaze.h" -#include "MBlazeFixupKinds.h" +#include "MBlazeELFWriterInfo.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCELFSymbolFlags.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCObjectFormat.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCValue.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -28,9 +31,9 @@ static unsigned getFixupKindSize(unsigned Kind) { switch (Kind) { default: assert(0 && "invalid fixup kind!"); case FK_Data_1: return 1; - case MBlaze::reloc_pcrel_2byte: + case FK_PCRel_2: case FK_Data_2: return 2; - case MBlaze::reloc_pcrel_4byte: + case FK_PCRel_4: case FK_Data_4: return 4; case FK_Data_8: return 8; } @@ -38,10 +41,21 @@ static unsigned getFixupKindSize(unsigned Kind) { namespace { +class MBlazeELFObjectWriter : public MCELFObjectTargetWriter { +public: + MBlazeELFObjectWriter(Triple::OSType OSType) + : MCELFObjectTargetWriter(/*is64Bit*/ false, OSType, ELF::EM_MBLAZE, + /*HasRelocationAddend*/ true) {} +}; + class MBlazeAsmBackend : public TargetAsmBackend { public: MBlazeAsmBackend(const Target &T) - : TargetAsmBackend(T) { + : TargetAsmBackend() { + } + + unsigned getNumFixupKinds() const { + return 2; } bool MayNeedRelaxation(const MCInst &Inst) const; @@ -55,13 +69,29 @@ public: } }; +static unsigned getRelaxedOpcode(unsigned Op) { + switch (Op) { + default: return Op; + case MBlaze::ADDIK: return MBlaze::ADDIK32; + case MBlaze::ORI: return MBlaze::ORI32; + case MBlaze::BRLID: return MBlaze::BRLID32; + } +} + bool MBlazeAsmBackend::MayNeedRelaxation(const MCInst &Inst) const { - return false; + if (getRelaxedOpcode(Inst.getOpcode()) == Inst.getOpcode()) + return false; + + bool hasExprOrImm = false; + for (unsigned i = 0; i < Inst.getNumOperands(); ++i) + hasExprOrImm |= Inst.getOperand(i).isExpr(); + + return hasExprOrImm; } void MBlazeAsmBackend::RelaxInstruction(const MCInst &Inst, MCInst &Res) const { - assert(0 && "MBlazeAsmBackend::RelaxInstruction() unimplemented"); - return; + Res = Inst; + Res.setOpcode(getRelaxedOpcode(Inst.getOpcode())); } bool MBlazeAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const { @@ -76,47 +106,29 @@ bool MBlazeAsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const { } // end anonymous namespace namespace { -// FIXME: This should be in a separate file. -// ELF is an ELF of course... class ELFMBlazeAsmBackend : public MBlazeAsmBackend { - MCELFObjectFormat Format; - public: Triple::OSType OSType; ELFMBlazeAsmBackend(const Target &T, Triple::OSType _OSType) - : MBlazeAsmBackend(T), OSType(_OSType) { - HasScatteredSymbols = true; - } - - virtual const MCObjectFormat &getObjectFormat() const { - return Format; - } - + : MBlazeAsmBackend(T), OSType(_OSType) { } - void ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF, + void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value) const; - bool isVirtualSection(const MCSection &Section) const { - const MCSectionELF &SE = static_cast<const MCSectionELF&>(Section); - return SE.getType() == MCSectionELF::SHT_NOBITS; - } - MCObjectWriter *createObjectWriter(raw_ostream &OS) const { - return createELFObjectWriter(OS, /*Is64Bit=*/false, - OSType, ELF::EM_MBLAZE, - /*IsLittleEndian=*/false, - /*HasRelocationAddend=*/true); + return createELFObjectWriter(new MBlazeELFObjectWriter(OSType), OS, + /*IsLittleEndian*/ false); } }; -void ELFMBlazeAsmBackend::ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF, - uint64_t Value) const { +void ELFMBlazeAsmBackend::ApplyFixup(const MCFixup &Fixup, char *Data, + unsigned DataSize, uint64_t Value) const { unsigned Size = getFixupKindSize(Fixup.getKind()); - assert(Fixup.getOffset() + Size <= DF.getContents().size() && + assert(Fixup.getOffset() + Size <= DataSize && "Invalid fixup offset!"); - char *data = DF.getContents().data() + Fixup.getOffset(); + char *data = Data + Fixup.getOffset(); switch (Size) { default: llvm_unreachable("Cannot fixup unknown value."); case 1: llvm_unreachable("Cannot fixup 1 byte value."); diff --git a/lib/Target/MBlaze/MBlazeAsmPrinter.cpp b/lib/Target/MBlaze/MBlazeAsmPrinter.cpp index d919d43..0016df5 100644 --- a/lib/Target/MBlaze/MBlazeAsmPrinter.cpp +++ b/lib/Target/MBlaze/MBlazeAsmPrinter.cpp @@ -60,6 +60,15 @@ namespace { return "MBlaze Assembly Printer"; } + void printSavedRegsBitmask(); + void emitFrameDirective(); + virtual void EmitFunctionBodyStart(); + virtual void EmitFunctionBodyEnd(); + virtual void EmitFunctionEntryLabel(); + + virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) + const; + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &O); @@ -106,6 +115,80 @@ namespace { // //===----------------------------------------------------------------------===// +// Print a 32 bit hex number with all numbers. +static void printHex32(unsigned int Value, raw_ostream &O) { + O << "0x"; + for (int i = 7; i >= 0; i--) + O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); +} + +// Create a bitmask with all callee saved registers for CPU or Floating Point +// registers. For CPU registers consider RA, GP and FP for saving if necessary. +void MBlazeAsmPrinter::printSavedRegsBitmask() { + const TargetFrameLowering *TFI = TM.getFrameLowering(); + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + + // CPU Saved Registers Bitmasks + unsigned int CPUBitmask = 0; + + // Set the CPU Bitmasks + const MachineFrameInfo *MFI = MF->getFrameInfo(); + const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + unsigned RegNum = MBlazeRegisterInfo::getRegisterNumbering(Reg); + if (MBlaze::GPRRegisterClass->contains(Reg)) + CPUBitmask |= (1 << RegNum); + } + + // Return Address and Frame registers must also be set in CPUBitmask. + if (TFI->hasFP(*MF)) + CPUBitmask |= (1 << MBlazeRegisterInfo:: + getRegisterNumbering(RI.getFrameRegister(*MF))); + + if (MFI->adjustsStack()) + CPUBitmask |= (1 << MBlazeRegisterInfo:: + getRegisterNumbering(RI.getRARegister())); + + // Print CPUBitmask + OutStreamer.EmitRawText("\t.mask\t0x" + Twine::utohexstr(CPUBitmask)); +} + +/// Frame Directive +void MBlazeAsmPrinter::emitFrameDirective() { + if (!OutStreamer.hasRawTextSupport()) + return; + + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + unsigned stkReg = RI.getFrameRegister(*MF); + unsigned retReg = RI.getRARegister(); + unsigned stkSze = MF->getFrameInfo()->getStackSize(); + + OutStreamer.EmitRawText("\t.frame\t" + + Twine(MBlazeInstPrinter::getRegisterName(stkReg)) + + "," + Twine(stkSze) + "," + + Twine(MBlazeInstPrinter::getRegisterName(retReg))); +} + +void MBlazeAsmPrinter::EmitFunctionEntryLabel() { + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText("\t.ent\t" + Twine(CurrentFnSym->getName())); + AsmPrinter::EmitFunctionEntryLabel(); +} + +void MBlazeAsmPrinter::EmitFunctionBodyStart() { + if (!OutStreamer.hasRawTextSupport()) + return; + + emitFrameDirective(); + printSavedRegsBitmask(); +} + +void MBlazeAsmPrinter::EmitFunctionBodyEnd() { + if (OutStreamer.hasRawTextSupport()) + OutStreamer.EmitRawText("\t.end\t" + Twine(CurrentFnSym->getName())); +} + //===----------------------------------------------------------------------===// void MBlazeAsmPrinter::EmitInstruction(const MachineInstr *MI) { MBlazeMCInstLower MCInstLowering(OutContext, *Mang, *this); @@ -115,14 +198,6 @@ void MBlazeAsmPrinter::EmitInstruction(const MachineInstr *MI) { OutStreamer.EmitInstruction(TmpInst); } -// Print a 32 bit hex number with all numbers. -static void printHex32(unsigned int Value, raw_ostream &O) { - O << "0x"; - for (int i = 7; i >= 0; i--) - O << utohexstr((Value & (0xF << (i*4))) >> (i*4)); -} - - // Print out an operand for an inline asm expression. bool MBlazeAsmPrinter:: PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, @@ -145,7 +220,7 @@ void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum, break; case MachineOperand::MO_Immediate: - O << (int)MO.getImm(); + O << (int32_t)MO.getImm(); break; case MachineOperand::MO_FPImmediate: { @@ -188,7 +263,7 @@ void MBlazeAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O) { const MachineOperand &MO = MI->getOperand(opNum); if (MO.isImm()) - O << (unsigned int)MO.getImm(); + O << (uint32_t)MO.getImm(); else printOperand(MI, opNum, O); } @@ -210,6 +285,39 @@ printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, printOperand(MI, opNum+1, O); } +/// isBlockOnlyReachableByFallthough - Return true if the basic block has +/// exactly one predecessor and the control transfer mechanism between +/// the predecessor and this block is a fall-through. +bool MBlazeAsmPrinter:: +isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { + // If this is a landing pad, it isn't a fall through. If it has no preds, + // then nothing falls through to it. + if (MBB->isLandingPad() || MBB->pred_empty()) + return false; + + // If there isn't exactly one predecessor, it can't be a fall through. + MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; + ++PI2; + if (PI2 != MBB->pred_end()) + return false; + + // The predecessor has to be immediately before this block. + const MachineBasicBlock *Pred = *PI; + + if (!Pred->isLayoutSuccessor(MBB)) + return false; + + // If the block is completely empty, then it definitely does fall through. + if (Pred->empty()) + return true; + + // Check if the last terminator is an unconditional branch. + MachineBasicBlock::const_iterator I = Pred->end(); + while (I != Pred->begin() && !(--I)->getDesc().isTerminator()) + ; // Noop + return I == Pred->end() || !I->getDesc().isBarrier(); +} + static MCInstPrinter *createMBlazeMCInstPrinter(const Target &T, unsigned SyntaxVariant, const MCAsmInfo &MAI) { diff --git a/lib/Target/MBlaze/MBlazeCallingConv.td b/lib/Target/MBlaze/MBlazeCallingConv.td index d037b0e..4962573 100644 --- a/lib/Target/MBlaze/MBlazeCallingConv.td +++ b/lib/Target/MBlaze/MBlazeCallingConv.td @@ -19,8 +19,10 @@ class CCIfSubtarget<string F, CCAction A>: def RetCC_MBlaze : CallingConv<[ // i32 are returned in registers R3, R4 - CCIfType<[i32], CCAssignToReg<[R3, R4]>>, + CCIfType<[i32,f32], CCAssignToReg<[R3, R4]>> +]>; - // f32 are returned in registers R3, R4 - CCIfType<[f32], CCAssignToReg<[R3, R4]>> +def CC_MBlaze : CallingConv<[ + CCIfType<[i32,f32], CCCustom<"CC_MBlaze_AssignReg">>, + CCIfType<[i32,f32], CCAssignToStack<4, 4>> ]>; diff --git a/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp b/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp index 32424e5..4399ee2 100644 --- a/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp +++ b/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp @@ -29,6 +29,14 @@ using namespace llvm; STATISTIC(FilledSlots, "Number of delay slots filled"); +namespace llvm { +cl::opt<bool> DisableDelaySlotFiller( + "disable-mblaze-delay-filler", + cl::init(false), + cl::desc("Disable the MBlaze delay slot filter."), + cl::Hidden); +} + namespace { struct Filler : public MachineFunctionPass { @@ -61,84 +69,161 @@ static bool hasImmInstruction(MachineBasicBlock::iterator &candidate) { // 16-bits requires an implicit IMM instruction. unsigned numOper = candidate->getNumOperands(); for (unsigned op = 0; op < numOper; ++op) { - if (candidate->getOperand(op).isImm() && - (candidate->getOperand(op).getImm() & 0xFFFFFFFFFFFF0000LL) != 0) - return true; + MachineOperand &mop = candidate->getOperand(op); + + // The operand requires more than 16-bits to represent. + if (mop.isImm() && (mop.getImm() < -0x8000 || mop.getImm() > 0x7fff)) + return true; + + // We must assume that unknown immediate values require more than + // 16-bits to represent. + if (mop.isGlobal() || mop.isSymbol()) + return true; // FIXME: we could probably check to see if the FP value happens // to not need an IMM instruction. For now we just always - // assume that FP values always do. - if (candidate->getOperand(op).isFPImm()) - return true; + // assume that FP values do. + if (mop.isFPImm()) + return true; } return false; } +static unsigned getLastRealOperand(MachineBasicBlock::iterator &instr) { + switch (instr->getOpcode()) { + default: return instr->getNumOperands(); + + // These instructions have a variable number of operands but the first two + // are the "real" operands that we care about during hazard detection. + case MBlaze::BRLID: + case MBlaze::BRALID: + case MBlaze::BRLD: + case MBlaze::BRALD: + return 2; + } +} + static bool delayHasHazard(MachineBasicBlock::iterator &candidate, MachineBasicBlock::iterator &slot) { + // Hazard check + MachineBasicBlock::iterator a = candidate; + MachineBasicBlock::iterator b = slot; + TargetInstrDesc desc = candidate->getDesc(); - // Loop over all of the operands in the branch instruction - // and make sure that none of them are defined by the - // candidate instruction. - unsigned numOper = slot->getNumOperands(); - for (unsigned op = 0; op < numOper; ++op) { - if (!slot->getOperand(op).isReg() || - !slot->getOperand(op).isUse() || - slot->getOperand(op).isImplicit()) - continue; - - unsigned cnumOper = candidate->getNumOperands(); - for (unsigned cop = 0; cop < cnumOper; ++cop) { - if (candidate->getOperand(cop).isReg() && - candidate->getOperand(cop).isDef() && - candidate->getOperand(cop).getReg() == - slot->getOperand(op).getReg()) - return true; - } + // MBB layout:- + // candidate := a0 = operation(a1, a2) + // ...middle bit... + // slot := b0 = operation(b1, b2) + + // Possible hazards:-/ + // 1. a1 or a2 was written during the middle bit + // 2. a0 was read or written during the middle bit + // 3. a0 is one or more of {b0, b1, b2} + // 4. b0 is one or more of {a1, a2} + // 5. a accesses memory, and the middle bit + // contains a store operation. + bool a_is_memory = desc.mayLoad() || desc.mayStore(); + + // Determine the number of operands in the slot instruction and in the + // candidate instruction. + const unsigned aend = getLastRealOperand(a); + const unsigned bend = getLastRealOperand(b); + + // Check hazards type 1, 2 and 5 by scanning the middle bit + MachineBasicBlock::iterator m = a; + for (++m; m != b; ++m) { + for (unsigned aop = 0; aop<aend; ++aop) { + bool aop_is_reg = a->getOperand(aop).isReg(); + if (!aop_is_reg) continue; + + bool aop_is_def = a->getOperand(aop).isDef(); + unsigned aop_reg = a->getOperand(aop).getReg(); + + const unsigned mend = getLastRealOperand(m); + for (unsigned mop = 0; mop<mend; ++mop) { + bool mop_is_reg = m->getOperand(mop).isReg(); + if (!mop_is_reg) continue; + + bool mop_is_def = m->getOperand(mop).isDef(); + unsigned mop_reg = m->getOperand(mop).getReg(); + + if (aop_is_def && (mop_reg == aop_reg)) + return true; // Hazard type 2, because aop = a0 + else if (mop_is_def && (mop_reg == aop_reg)) + return true; // Hazard type 1, because aop in {a1, a2} + } } - // There are no hazards between the two instructions - return false; -} + // Check hazard type 5 + if (a_is_memory && m->getDesc().mayStore()) + return true; + } + + // Check hazard type 3 & 4 + for (unsigned aop = 0; aop<aend; ++aop) { + if (a->getOperand(aop).isReg()) { + unsigned aop_reg = a->getOperand(aop).getReg(); -static bool usedBeforeDelaySlot(MachineBasicBlock::iterator &candidate, - MachineBasicBlock::iterator &slot) { - MachineBasicBlock::iterator I = candidate; - for (++I; I != slot; ++I) { - unsigned numOper = I->getNumOperands(); - for (unsigned op = 0; op < numOper; ++op) { - if (I->getOperand(op).isReg() && - I->getOperand(op).isUse()) { - unsigned reg = I->getOperand(op).getReg(); - unsigned cops = candidate->getNumOperands(); - for (unsigned cop = 0; cop < cops; ++cop) { - if (candidate->getOperand(cop).isReg() && - candidate->getOperand(cop).isDef() && - candidate->getOperand(cop).getReg() == reg) - return true; - } - } + for (unsigned bop = 0; bop<bend; ++bop) { + if (b->getOperand(bop).isReg() && !b->getOperand(bop).isImplicit()) { + unsigned bop_reg = b->getOperand(bop).getReg(); + if (aop_reg == bop_reg) + return true; } + } + } } return false; } +static bool isDelayFiller(MachineBasicBlock &MBB, + MachineBasicBlock::iterator candidate) { + if (candidate == MBB.begin()) + return false; + + TargetInstrDesc brdesc = (--candidate)->getDesc(); + return (brdesc.hasDelaySlot()); +} + +static bool hasUnknownSideEffects(MachineBasicBlock::iterator &I) { + if (!I->hasUnmodeledSideEffects()) + return false; + + unsigned op = I->getOpcode(); + if (op == MBlaze::ADDK || op == MBlaze::ADDIK || + op == MBlaze::ADDC || op == MBlaze::ADDIC || + op == MBlaze::ADDKC || op == MBlaze::ADDIKC || + op == MBlaze::RSUBK || op == MBlaze::RSUBIK || + op == MBlaze::RSUBC || op == MBlaze::RSUBIC || + op == MBlaze::RSUBKC || op == MBlaze::RSUBIKC) + return false; + + return true; +} + static MachineBasicBlock::iterator -findDelayInstr(MachineBasicBlock &MBB,MachineBasicBlock::iterator &slot) { - MachineBasicBlock::iterator found = MBB.end(); - for (MachineBasicBlock::iterator I = MBB.begin(); I != slot; ++I) { - TargetInstrDesc desc = I->getDesc(); - if (desc.hasDelaySlot() || desc.isBranch() || - desc.mayLoad() || desc. mayStore() || - hasImmInstruction(I) || delayHasHazard(I,slot) || - usedBeforeDelaySlot(I,slot)) continue; - - found = I; +findDelayInstr(MachineBasicBlock &MBB,MachineBasicBlock::iterator slot) { + MachineBasicBlock::iterator I = slot; + while (true) { + if (I == MBB.begin()) + break; + + --I; + TargetInstrDesc desc = I->getDesc(); + if (desc.hasDelaySlot() || desc.isBranch() || isDelayFiller(MBB,I) || + desc.isCall() || desc.isReturn() || desc.isBarrier() || + hasUnknownSideEffects(I)) + break; + + if (hasImmInstruction(I) || delayHasHazard(I,slot)) + continue; + + return I; } - return found; + return MBB.end(); } /// runOnMachineBasicBlock - Fill in delay slots for the given basic block. @@ -148,17 +233,19 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) if (I->getDesc().hasDelaySlot()) { + MachineBasicBlock::iterator D = MBB.end(); MachineBasicBlock::iterator J = I; - MachineBasicBlock::iterator D = findDelayInstr(MBB,I); - ++J; + if (!DisableDelaySlotFiller) + D = findDelayInstr(MBB,I); + ++FilledSlots; Changed = true; if (D == MBB.end()) - BuildMI(MBB, J, I->getDebugLoc(), TII->get(MBlaze::NOP)); + BuildMI(MBB, ++J, I->getDebugLoc(), TII->get(MBlaze::NOP)); else - MBB.splice(J, &MBB, D); + MBB.splice(++J, &MBB, D); } return Changed; } diff --git a/lib/Target/MBlaze/MBlazeELFWriterInfo.cpp b/lib/Target/MBlaze/MBlazeELFWriterInfo.cpp index cf6312f..3f26ed1 100644 --- a/lib/Target/MBlaze/MBlazeELFWriterInfo.cpp +++ b/lib/Target/MBlaze/MBlazeELFWriterInfo.cpp @@ -14,6 +14,7 @@ #include "MBlazeELFWriterInfo.h" #include "MBlazeRelocations.h" #include "llvm/Function.h" +#include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" @@ -34,9 +35,9 @@ MBlazeELFWriterInfo::~MBlazeELFWriterInfo() {} unsigned MBlazeELFWriterInfo::getRelocationType(unsigned MachineRelTy) const { switch (MachineRelTy) { case MBlaze::reloc_pcrel_word: - return R_MICROBLAZE_64_PCREL; + return ELF::R_MICROBLAZE_64_PCREL; case MBlaze::reloc_absolute_word: - return R_MICROBLAZE_NONE; + return ELF::R_MICROBLAZE_NONE; default: llvm_unreachable("unknown mblaze machine relocation type"); } @@ -46,9 +47,9 @@ unsigned MBlazeELFWriterInfo::getRelocationType(unsigned MachineRelTy) const { long int MBlazeELFWriterInfo::getDefaultAddendForRelTy(unsigned RelTy, long int Modifier) const { switch (RelTy) { - case R_MICROBLAZE_32_PCREL: + case ELF::R_MICROBLAZE_32_PCREL: return Modifier - 4; - case R_MICROBLAZE_32: + case ELF::R_MICROBLAZE_32: return Modifier; default: llvm_unreachable("unknown mblaze relocation type"); @@ -59,22 +60,22 @@ long int MBlazeELFWriterInfo::getDefaultAddendForRelTy(unsigned RelTy, unsigned MBlazeELFWriterInfo::getRelocationTySize(unsigned RelTy) const { // FIXME: Most of these sizes are guesses based on the name switch (RelTy) { - case R_MICROBLAZE_32: - case R_MICROBLAZE_32_PCREL: - case R_MICROBLAZE_32_PCREL_LO: - case R_MICROBLAZE_32_LO: - case R_MICROBLAZE_SRO32: - case R_MICROBLAZE_SRW32: - case R_MICROBLAZE_32_SYM_OP_SYM: - case R_MICROBLAZE_GOTOFF_32: + case ELF::R_MICROBLAZE_32: + case ELF::R_MICROBLAZE_32_PCREL: + case ELF::R_MICROBLAZE_32_PCREL_LO: + case ELF::R_MICROBLAZE_32_LO: + case ELF::R_MICROBLAZE_SRO32: + case ELF::R_MICROBLAZE_SRW32: + case ELF::R_MICROBLAZE_32_SYM_OP_SYM: + case ELF::R_MICROBLAZE_GOTOFF_32: return 32; - case R_MICROBLAZE_64_PCREL: - case R_MICROBLAZE_64: - case R_MICROBLAZE_GOTPC_64: - case R_MICROBLAZE_GOT_64: - case R_MICROBLAZE_PLT_64: - case R_MICROBLAZE_GOTOFF_64: + case ELF::R_MICROBLAZE_64_PCREL: + case ELF::R_MICROBLAZE_64: + case ELF::R_MICROBLAZE_GOTPC_64: + case ELF::R_MICROBLAZE_GOT_64: + case ELF::R_MICROBLAZE_PLT_64: + case ELF::R_MICROBLAZE_GOTOFF_64: return 64; } @@ -84,10 +85,10 @@ unsigned MBlazeELFWriterInfo::getRelocationTySize(unsigned RelTy) const { bool MBlazeELFWriterInfo::isPCRelativeRel(unsigned RelTy) const { // FIXME: Most of these are guesses based on the name switch (RelTy) { - case R_MICROBLAZE_32_PCREL: - case R_MICROBLAZE_64_PCREL: - case R_MICROBLAZE_32_PCREL_LO: - case R_MICROBLAZE_GOTPC_64: + case ELF::R_MICROBLAZE_32_PCREL: + case ELF::R_MICROBLAZE_64_PCREL: + case ELF::R_MICROBLAZE_32_PCREL_LO: + case ELF::R_MICROBLAZE_GOTPC_64: return true; } @@ -101,7 +102,7 @@ unsigned MBlazeELFWriterInfo::getAbsoluteLabelMachineRelTy() const { long int MBlazeELFWriterInfo::computeRelocation(unsigned SymOffset, unsigned RelOffset, unsigned RelTy) const { - if (RelTy == R_MICROBLAZE_32_PCREL || R_MICROBLAZE_64_PCREL) + if (RelTy == ELF::R_MICROBLAZE_32_PCREL || ELF::R_MICROBLAZE_64_PCREL) return SymOffset - (RelOffset + 4); else assert("computeRelocation unknown for this relocation type"); diff --git a/lib/Target/MBlaze/MBlazeELFWriterInfo.h b/lib/Target/MBlaze/MBlazeELFWriterInfo.h index abea992..63bfc0d 100644 --- a/lib/Target/MBlaze/MBlazeELFWriterInfo.h +++ b/lib/Target/MBlaze/MBlazeELFWriterInfo.h @@ -19,33 +19,6 @@ namespace llvm { class MBlazeELFWriterInfo : public TargetELFWriterInfo { - - // ELF Relocation types for MBlaze - enum MBlazeRelocationType { - R_MICROBLAZE_NONE = 0, - R_MICROBLAZE_32 = 1, - R_MICROBLAZE_32_PCREL = 2, - R_MICROBLAZE_64_PCREL = 3, - R_MICROBLAZE_32_PCREL_LO = 4, - R_MICROBLAZE_64 = 5, - R_MICROBLAZE_32_LO = 6, - R_MICROBLAZE_SRO32 = 7, - R_MICROBLAZE_SRW32 = 8, - R_MICROBLAZE_64_NONE = 9, - R_MICROBLAZE_32_SYM_OP_SYM = 10, - R_MICROBLAZE_GNU_VTINHERIT = 11, - R_MICROBLAZE_GNU_VTENTRY = 12, - R_MICROBLAZE_GOTPC_64 = 13, - R_MICROBLAZE_GOT_64 = 14, - R_MICROBLAZE_PLT_64 = 15, - R_MICROBLAZE_REL = 16, - R_MICROBLAZE_JUMP_SLOT = 17, - R_MICROBLAZE_GLOB_DAT = 18, - R_MICROBLAZE_GOTOFF_64 = 19, - R_MICROBLAZE_GOTOFF_32 = 20, - R_MICROBLAZE_COPY = 21 - }; - public: MBlazeELFWriterInfo(TargetMachine &TM); virtual ~MBlazeELFWriterInfo(); diff --git a/lib/Target/MBlaze/MBlazeFixupKinds.h b/lib/Target/MBlaze/MBlazeFixupKinds.h deleted file mode 100644 index 72466ca..0000000 --- a/lib/Target/MBlaze/MBlazeFixupKinds.h +++ /dev/null @@ -1,24 +0,0 @@ -//===-- MBlaze/MBlazeFixupKinds.h - MBlaze Fixup Entries --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MBLAZE_MBLAZEFIXUPKINDS_H -#define LLVM_MBLAZE_MBLAZEFIXUPKINDS_H - -#include "llvm/MC/MCFixup.h" - -namespace llvm { -namespace MBlaze { -enum Fixups { - reloc_pcrel_4byte = FirstTargetFixupKind, // 32-bit pcrel, e.g. a brlid - reloc_pcrel_2byte // 16-bit pcrel, e.g. beqid -}; -} -} - -#endif diff --git a/lib/Target/MBlaze/MBlazeFrameInfo.cpp b/lib/Target/MBlaze/MBlazeFrameInfo.cpp deleted file mode 100644 index c1209a4..0000000 --- a/lib/Target/MBlaze/MBlazeFrameInfo.cpp +++ /dev/null @@ -1,183 +0,0 @@ -//=======- MBlazeFrameInfo.cpp - MBlaze Frame Information ------*- C++ -*-====// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the MBlaze implementation of TargetFrameInfo class. -// -//===----------------------------------------------------------------------===// - -#include "MBlazeFrameInfo.h" -#include "MBlazeInstrInfo.h" -#include "MBlazeMachineFunction.h" -#include "llvm/Function.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Support/CommandLine.h" - -using namespace llvm; - - -//===----------------------------------------------------------------------===// -// -// Stack Frame Processing methods -// +----------------------------+ -// -// The stack is allocated decrementing the stack pointer on -// the first instruction of a function prologue. Once decremented, -// all stack references are are done through a positive offset -// from the stack/frame pointer, so the stack is considered -// to grow up. -// -//===----------------------------------------------------------------------===// - -void MBlazeFrameInfo::adjustMBlazeStackFrame(MachineFunction &MF) const { - MachineFrameInfo *MFI = MF.getFrameInfo(); - MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); - const MBlazeRegisterInfo *RegInfo = - static_cast<const MBlazeRegisterInfo*>(MF.getTarget().getRegisterInfo()); - - // See the description at MicroBlazeMachineFunction.h - int TopCPUSavedRegOff = -1; - - // Adjust CPU Callee Saved Registers Area. Registers RA and FP must - // be saved in this CPU Area there is the need. This whole Area must - // be aligned to the default Stack Alignment requirements. - unsigned StackOffset = MFI->getStackSize(); - unsigned RegSize = 4; - - // Replace the dummy '0' SPOffset by the negative offsets, as explained on - // LowerFORMAL_ARGUMENTS. Leaving '0' for while is necessary to avoid - // the approach done by calculateFrameObjectOffsets to the stack frame. - MBlazeFI->adjustLoadArgsFI(MFI); - MBlazeFI->adjustStoreVarArgsFI(MFI); - - if (RegInfo->hasFP(MF)) { - MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), - StackOffset); - MBlazeFI->setFPStackOffset(StackOffset); - TopCPUSavedRegOff = StackOffset; - StackOffset += RegSize; - } - - if (MFI->adjustsStack()) { - MBlazeFI->setRAStackOffset(0); - MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), - StackOffset); - TopCPUSavedRegOff = StackOffset; - StackOffset += RegSize; - } - - // Update frame info - MFI->setStackSize(StackOffset); - - // Recalculate the final tops offset. The final values must be '0' - // if there isn't a callee saved register for CPU or FPU, otherwise - // a negative offset is needed. - if (TopCPUSavedRegOff >= 0) - MBlazeFI->setCPUTopSavedRegOff(TopCPUSavedRegOff-StackOffset); -} - -void MBlazeFrameInfo::emitPrologue(MachineFunction &MF) const { - MachineBasicBlock &MBB = MF.front(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - const MBlazeRegisterInfo *RegInfo = - static_cast<const MBlazeRegisterInfo*>(MF.getTarget().getRegisterInfo()); - const MBlazeInstrInfo &TII = - *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo()); - MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); - MachineBasicBlock::iterator MBBI = MBB.begin(); - DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); - - // Get the right frame order for MBlaze. - adjustMBlazeStackFrame(MF); - - // Get the number of bytes to allocate from the FrameInfo. - unsigned StackSize = MFI->getStackSize(); - - // No need to allocate space on the stack. - if (StackSize == 0 && !MFI->adjustsStack()) return; - if (StackSize < 28 && MFI->adjustsStack()) StackSize = 28; - - int FPOffset = MBlazeFI->getFPStackOffset(); - int RAOffset = MBlazeFI->getRAStackOffset(); - - // Adjust stack : addi R1, R1, -imm - BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADDI), MBlaze::R1) - .addReg(MBlaze::R1).addImm(-StackSize); - - // Save the return address only if the function isnt a leaf one. - // swi R15, R1, stack_loc - if (MFI->adjustsStack()) { - BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI)) - .addReg(MBlaze::R15).addReg(MBlaze::R1).addImm(RAOffset); - } - - // if framepointer enabled, save it and set it - // to point to the stack pointer - if (RegInfo->hasFP(MF)) { - // swi R19, R1, stack_loc - BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI)) - .addReg(MBlaze::R19).addReg(MBlaze::R1).addImm(FPOffset); - - // add R19, R1, R0 - BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADD), MBlaze::R19) - .addReg(MBlaze::R1).addReg(MBlaze::R0); - } -} - -void MBlazeFrameInfo::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - MachineBasicBlock::iterator MBBI = prior(MBB.end()); - MachineFrameInfo *MFI = MF.getFrameInfo(); - MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); - const MBlazeRegisterInfo *RegInfo = - static_cast<const MBlazeRegisterInfo*>(MF.getTarget().getRegisterInfo()); - const MBlazeInstrInfo &TII = - *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo()); - - DebugLoc dl = MBBI->getDebugLoc(); - - // Get the FI's where RA and FP are saved. - int FPOffset = MBlazeFI->getFPStackOffset(); - int RAOffset = MBlazeFI->getRAStackOffset(); - - // if framepointer enabled, restore it and restore the - // stack pointer - if (RegInfo->hasFP(MF)) { - // add R1, R19, R0 - BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R1) - .addReg(MBlaze::R19).addReg(MBlaze::R0); - - // lwi R19, R1, stack_loc - BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R19) - .addReg(MBlaze::R1).addImm(FPOffset); - } - - // Restore the return address only if the function isnt a leaf one. - // lwi R15, R1, stack_loc - if (MFI->adjustsStack()) { - BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15) - .addReg(MBlaze::R1).addImm(RAOffset); - } - - // Get the number of bytes from FrameInfo - int StackSize = (int) MFI->getStackSize(); - if (StackSize < 28 && MFI->adjustsStack()) StackSize = 28; - - // adjust stack. - // addi R1, R1, imm - if (StackSize) { - BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDI), MBlaze::R1) - .addReg(MBlaze::R1).addImm(StackSize); - } -} diff --git a/lib/Target/MBlaze/MBlazeFrameLowering.cpp b/lib/Target/MBlaze/MBlazeFrameLowering.cpp new file mode 100644 index 0000000..e763902 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeFrameLowering.cpp @@ -0,0 +1,450 @@ +//=======- MBlazeFrameLowering.cpp - MBlaze Frame Information ------*- C++ -*-====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the MBlaze implementation of TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mblaze-frame-lowering" + +#include "MBlazeFrameLowering.h" +#include "MBlazeInstrInfo.h" +#include "MBlazeMachineFunction.h" +#include "InstPrinter/MBlazeInstPrinter.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace llvm { + cl::opt<bool> DisableStackAdjust( + "disable-mblaze-stack-adjust", + cl::init(false), + cl::desc("Disable MBlaze stack layout adjustment."), + cl::Hidden); +} + +static void replaceFrameIndexes(MachineFunction &MF, + SmallVector<std::pair<int,int64_t>, 16> &FR) { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + const SmallVector<std::pair<int,int64_t>, 16>::iterator FRB = FR.begin(); + const SmallVector<std::pair<int,int64_t>, 16>::iterator FRE = FR.end(); + + SmallVector<std::pair<int,int64_t>, 16>::iterator FRI = FRB; + for (; FRI != FRE; ++FRI) { + MFI->RemoveStackObject(FRI->first); + int NFI = MFI->CreateFixedObject(4, FRI->second, true); + MBlazeFI->recordReplacement(FRI->first, NFI); + + for (MachineFunction::iterator MB=MF.begin(), ME=MF.end(); MB!=ME; ++MB) { + MachineBasicBlock::iterator MBB = MB->begin(); + const MachineBasicBlock::iterator MBE = MB->end(); + + for (; MBB != MBE; ++MBB) { + MachineInstr::mop_iterator MIB = MBB->operands_begin(); + const MachineInstr::mop_iterator MIE = MBB->operands_end(); + + for (MachineInstr::mop_iterator MII = MIB; MII != MIE; ++MII) { + if (!MII->isFI() || MII->getIndex() != FRI->first) continue; + DEBUG(dbgs() << "FOUND FI#" << MII->getIndex() << "\n"); + MII->setIndex(NFI); + } + } + } + } +} + +//===----------------------------------------------------------------------===// +// +// Stack Frame Processing methods +// +----------------------------+ +// +// The stack is allocated decrementing the stack pointer on +// the first instruction of a function prologue. Once decremented, +// all stack references are are done through a positive offset +// from the stack/frame pointer, so the stack is considered +// to grow up. +// +//===----------------------------------------------------------------------===// + +static void analyzeFrameIndexes(MachineFunction &MF) { + if (DisableStackAdjust) return; + + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + + MachineRegisterInfo::livein_iterator LII = MRI.livein_begin(); + MachineRegisterInfo::livein_iterator LIE = MRI.livein_end(); + const SmallVector<int, 16> &LiveInFI = MBlazeFI->getLiveIn(); + SmallVector<MachineInstr*, 16> EraseInstr; + SmallVector<std::pair<int,int64_t>, 16> FrameRelocate; + + MachineBasicBlock *MBB = MF.getBlockNumbered(0); + MachineBasicBlock::iterator MIB = MBB->begin(); + MachineBasicBlock::iterator MIE = MBB->end(); + + int StackAdjust = 0; + int StackOffset = -28; + + // In this loop we are searching frame indexes that corrospond to incoming + // arguments that are already in the stack. We look for instruction sequences + // like the following: + // + // LWI REG, FI1, 0 + // ... + // SWI REG, FI2, 0 + // + // As long as there are no defs of REG in the ... part, we can eliminate + // the SWI instruction because the value has already been stored to the + // stack by the caller. All we need to do is locate FI at the correct + // stack location according to the calling convensions. + // + // Additionally, if the SWI operation kills the def of REG then we don't + // need the LWI operation so we can erase it as well. + for (unsigned i = 0, e = LiveInFI.size(); i < e; ++i) { + for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) { + if (I->getOpcode() != MBlaze::LWI || I->getNumOperands() != 3 || + !I->getOperand(1).isFI() || !I->getOperand(0).isReg() || + I->getOperand(1).getIndex() != LiveInFI[i]) continue; + + unsigned FIReg = I->getOperand(0).getReg(); + MachineBasicBlock::iterator SI = I; + for (SI++; SI != MIE; ++SI) { + if (!SI->getOperand(0).isReg() || + !SI->getOperand(1).isFI() || + SI->getOpcode() != MBlaze::SWI) continue; + + int FI = SI->getOperand(1).getIndex(); + if (SI->getOperand(0).getReg() != FIReg || + MFI->isFixedObjectIndex(FI) || + MFI->getObjectSize(FI) != 4) continue; + + if (SI->getOperand(0).isDef()) break; + + if (SI->getOperand(0).isKill()) { + DEBUG(dbgs() << "LWI for FI#" << I->getOperand(1).getIndex() + << " removed\n"); + EraseInstr.push_back(I); + } + + EraseInstr.push_back(SI); + DEBUG(dbgs() << "SWI for FI#" << FI << " removed\n"); + + FrameRelocate.push_back(std::make_pair(FI,StackOffset)); + DEBUG(dbgs() << "FI#" << FI << " relocated to " << StackOffset << "\n"); + + StackOffset -= 4; + StackAdjust += 4; + break; + } + } + } + + // In this loop we are searching for frame indexes that corrospond to + // incoming arguments that are in registers. We look for instruction + // sequences like the following: + // + // ... SWI REG, FI, 0 + // + // As long as the ... part does not define REG and if REG is an incoming + // parameter register then we know that, according to ABI convensions, the + // caller has allocated stack space for it already. Instead of allocating + // stack space on our frame, we record the correct location in the callers + // frame. + for (MachineRegisterInfo::livein_iterator LI = LII; LI != LIE; ++LI) { + for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) { + if (I->definesRegister(LI->first)) + break; + + if (I->getOpcode() != MBlaze::SWI || I->getNumOperands() != 3 || + !I->getOperand(1).isFI() || !I->getOperand(0).isReg() || + I->getOperand(1).getIndex() < 0) continue; + + if (I->getOperand(0).getReg() == LI->first) { + int FI = I->getOperand(1).getIndex(); + MBlazeFI->recordLiveIn(FI); + + int FILoc = 0; + switch (LI->first) { + default: llvm_unreachable("invalid incoming parameter!"); + case MBlaze::R5: FILoc = -4; break; + case MBlaze::R6: FILoc = -8; break; + case MBlaze::R7: FILoc = -12; break; + case MBlaze::R8: FILoc = -16; break; + case MBlaze::R9: FILoc = -20; break; + case MBlaze::R10: FILoc = -24; break; + } + + StackAdjust += 4; + FrameRelocate.push_back(std::make_pair(FI,FILoc)); + DEBUG(dbgs() << "FI#" << FI << " relocated to " << FILoc << "\n"); + break; + } + } + } + + // Go ahead and erase all of the instructions that we determined were + // no longer needed. + for (int i = 0, e = EraseInstr.size(); i < e; ++i) + MBB->erase(EraseInstr[i]); + + // Replace all of the frame indexes that we have relocated with new + // fixed object frame indexes. + replaceFrameIndexes(MF, FrameRelocate); +} + +static void interruptFrameLayout(MachineFunction &MF) { + const Function *F = MF.getFunction(); + llvm::CallingConv::ID CallConv = F->getCallingConv(); + + // If this function is not using either the interrupt_handler + // calling convention or the save_volatiles calling convention + // then we don't need to do any additional frame layout. + if (CallConv != llvm::CallingConv::MBLAZE_INTR && + CallConv != llvm::CallingConv::MBLAZE_SVOL) + return; + + MachineFrameInfo *MFI = MF.getFrameInfo(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + const MBlazeInstrInfo &TII = + *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo()); + + // Determine if the calling convention is the interrupt_handler + // calling convention. Some pieces of the prologue and epilogue + // only need to be emitted if we are lowering and interrupt handler. + bool isIntr = CallConv == llvm::CallingConv::MBLAZE_INTR; + + // Determine where to put prologue and epilogue additions + MachineBasicBlock &MENT = MF.front(); + MachineBasicBlock &MEXT = MF.back(); + + MachineBasicBlock::iterator MENTI = MENT.begin(); + MachineBasicBlock::iterator MEXTI = prior(MEXT.end()); + + DebugLoc ENTDL = MENTI != MENT.end() ? MENTI->getDebugLoc() : DebugLoc(); + DebugLoc EXTDL = MEXTI != MEXT.end() ? MEXTI->getDebugLoc() : DebugLoc(); + + // Store the frame indexes generated during prologue additions for use + // when we are generating the epilogue additions. + SmallVector<int, 10> VFI; + + // Build the prologue SWI for R3 - R12 if needed. Note that R11 must + // always have a SWI because it is used when processing RMSR. + for (unsigned r = MBlaze::R3; r <= MBlaze::R12; ++r) { + if (!MRI.isPhysRegUsed(r) && !(isIntr && r == MBlaze::R11)) continue; + + int FI = MFI->CreateStackObject(4,4,false,false); + VFI.push_back(FI); + + BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), r) + .addFrameIndex(FI).addImm(0); + } + + // Build the prologue SWI for R17, R18 + int R17FI = MFI->CreateStackObject(4,4,false,false); + int R18FI = MFI->CreateStackObject(4,4,false,false); + + BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R17) + .addFrameIndex(R17FI).addImm(0); + + BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R18) + .addFrameIndex(R18FI).addImm(0); + + // Buid the prologue SWI and the epilogue LWI for RMSR if needed + if (isIntr) { + int MSRFI = MFI->CreateStackObject(4,4,false,false); + BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::MFS), MBlaze::R11) + .addReg(MBlaze::RMSR); + BuildMI(MENT, MENTI, ENTDL, TII.get(MBlaze::SWI), MBlaze::R11) + .addFrameIndex(MSRFI).addImm(0); + + BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R11) + .addFrameIndex(MSRFI).addImm(0); + BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::MTS), MBlaze::RMSR) + .addReg(MBlaze::R11); + } + + // Build the epilogue LWI for R17, R18 + BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R18) + .addFrameIndex(R18FI).addImm(0); + + BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), MBlaze::R17) + .addFrameIndex(R17FI).addImm(0); + + // Build the epilogue LWI for R3 - R12 if needed + for (unsigned r = MBlaze::R12, i = VFI.size(); r >= MBlaze::R3; --r) { + if (!MRI.isPhysRegUsed(r)) continue; + BuildMI(MEXT, MEXTI, EXTDL, TII.get(MBlaze::LWI), r) + .addFrameIndex(VFI[--i]).addImm(0); + } +} + +static void determineFrameLayout(MachineFunction &MF) { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + + // Replace the dummy '0' SPOffset by the negative offsets, as explained on + // LowerFORMAL_ARGUMENTS. Leaving '0' for while is necessary to avoid + // the approach done by calculateFrameObjectOffsets to the stack frame. + MBlazeFI->adjustLoadArgsFI(MFI); + MBlazeFI->adjustStoreVarArgsFI(MFI); + + // Get the number of bytes to allocate from the FrameInfo + unsigned FrameSize = MFI->getStackSize(); + DEBUG(dbgs() << "Original Frame Size: " << FrameSize << "\n" ); + + // Get the alignments provided by the target, and the maximum alignment + // (if any) of the fixed frame objects. + // unsigned MaxAlign = MFI->getMaxAlignment(); + unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment(); + unsigned AlignMask = TargetAlign - 1; + + // Make sure the frame is aligned. + FrameSize = (FrameSize + AlignMask) & ~AlignMask; + MFI->setStackSize(FrameSize); + DEBUG(dbgs() << "Aligned Frame Size: " << FrameSize << "\n" ); +} + +int MBlazeFrameLowering::getFrameIndexOffset(const MachineFunction &MF, int FI) + const { + const MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + if (MBlazeFI->hasReplacement(FI)) + FI = MBlazeFI->getReplacement(FI); + return TargetFrameLowering::getFrameIndexOffset(MF,FI); +} + +// hasFP - Return true if the specified function should have a dedicated frame +// pointer register. This is true if the function has variable sized allocas or +// if frame pointer elimination is disabled. +bool MBlazeFrameLowering::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects(); +} + +void MBlazeFrameLowering::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + const MBlazeInstrInfo &TII = + *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo()); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + MachineBasicBlock::iterator MBBI = MBB.begin(); + DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); + + llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); + bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR; + + // Determine the correct frame layout + determineFrameLayout(MF); + + // Get the number of bytes to allocate from the FrameInfo. + unsigned StackSize = MFI->getStackSize(); + + // No need to allocate space on the stack. + if (StackSize == 0 && !MFI->adjustsStack() && !requiresRA) return; + + int FPOffset = MBlazeFI->getFPStackOffset(); + int RAOffset = MBlazeFI->getRAStackOffset(); + + // Adjust stack : addi R1, R1, -imm + BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADDIK), MBlaze::R1) + .addReg(MBlaze::R1).addImm(-StackSize); + + // swi R15, R1, stack_loc + if (MFI->adjustsStack() || requiresRA) { + BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI)) + .addReg(MBlaze::R15).addReg(MBlaze::R1).addImm(RAOffset); + } + + if (hasFP(MF)) { + // swi R19, R1, stack_loc + BuildMI(MBB, MBBI, DL, TII.get(MBlaze::SWI)) + .addReg(MBlaze::R19).addReg(MBlaze::R1).addImm(FPOffset); + + // add R19, R1, R0 + BuildMI(MBB, MBBI, DL, TII.get(MBlaze::ADD), MBlaze::R19) + .addReg(MBlaze::R1).addReg(MBlaze::R0); + } +} + +void MBlazeFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + const MBlazeInstrInfo &TII = + *static_cast<const MBlazeInstrInfo*>(MF.getTarget().getInstrInfo()); + + DebugLoc dl = MBBI->getDebugLoc(); + + llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); + bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR; + + // Get the FI's where RA and FP are saved. + int FPOffset = MBlazeFI->getFPStackOffset(); + int RAOffset = MBlazeFI->getRAStackOffset(); + + if (hasFP(MF)) { + // add R1, R19, R0 + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R1) + .addReg(MBlaze::R19).addReg(MBlaze::R0); + + // lwi R19, R1, stack_loc + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R19) + .addReg(MBlaze::R1).addImm(FPOffset); + } + + // lwi R15, R1, stack_loc + if (MFI->adjustsStack() || requiresRA) { + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15) + .addReg(MBlaze::R1).addImm(RAOffset); + } + + // Get the number of bytes from FrameInfo + int StackSize = (int) MFI->getStackSize(); + + // addi R1, R1, imm + if (StackSize) { + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDIK), MBlaze::R1) + .addReg(MBlaze::R1).addImm(StackSize); + } +} + +void MBlazeFrameLowering:: +processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + llvm::CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); + bool requiresRA = CallConv == llvm::CallingConv::MBLAZE_INTR; + + if (MFI->adjustsStack() || requiresRA) { + MBlazeFI->setRAStackOffset(0); + MFI->CreateFixedObject(4,0,true); + } + + if (hasFP(MF)) { + MBlazeFI->setFPStackOffset(4); + MFI->CreateFixedObject(4,4,true); + } + + interruptFrameLayout(MF); + analyzeFrameIndexes(MF); +} diff --git a/lib/Target/MBlaze/MBlazeFrameInfo.h b/lib/Target/MBlaze/MBlazeFrameLowering.h index 3e96ee3..8be15bf 100644 --- a/lib/Target/MBlaze/MBlazeFrameInfo.h +++ b/lib/Target/MBlaze/MBlazeFrameLowering.h @@ -1,4 +1,4 @@ -//=-- MBlazeFrameInfo.h - Define TargetFrameInfo for MicroBlaze --*- C++ -*--=// +//=- MBlazeFrameLowering.h - Define frame lowering for MicroBlaze -*- C++ -*-=// // // The LLVM Compiler Infrastructure // @@ -11,27 +11,25 @@ // //===----------------------------------------------------------------------===// -#ifndef ALPHA_FRAMEINFO_H -#define ALPHA_FRAMEINFO_H +#ifndef MBLAZE_FRAMEINFO_H +#define MBLAZE_FRAMEINFO_H #include "MBlaze.h" #include "MBlazeSubtarget.h" -#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetFrameLowering.h" namespace llvm { class MBlazeSubtarget; -class MBlazeFrameInfo : public TargetFrameInfo { +class MBlazeFrameLowering : public TargetFrameLowering { protected: const MBlazeSubtarget &STI; public: - explicit MBlazeFrameInfo(const MBlazeSubtarget &sti) - : TargetFrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0), STI(sti) { + explicit MBlazeFrameLowering(const MBlazeSubtarget &sti) + : TargetFrameLowering(TargetFrameLowering::StackGrowsUp, 4, 0), STI(sti) { } - void adjustMBlazeStackFrame(MachineFunction &MF) const; - /// targetHandlesStackFrameRounding - Returns true if the target is /// responsible for rounding up the stack frame (probably at emitPrologue /// time). @@ -41,6 +39,13 @@ public: /// the function. void emitPrologue(MachineFunction &MF) const; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + bool hasFP(const MachineFunction &MF) const; + + int getFrameIndexOffset(const MachineFunction &MF, int FI) const; + + virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const; }; } // End llvm namespace diff --git a/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp b/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp index 9924e67..6b43497 100644 --- a/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp +++ b/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp @@ -210,7 +210,7 @@ SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) { int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex(); EVT VT = Node->getValueType(0); SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); - unsigned Opc = MBlaze::ADDI; + unsigned Opc = MBlaze::ADDIK; if (Node->hasOneUse()) return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, imm); return CurDAG->getMachineNode(Opc, dl, VT, TFI, imm); @@ -248,7 +248,7 @@ SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) { // Emit Jump and Link Register SDNode *ResNode = CurDAG->getMachineNode(MBlaze::BRLID, dl, MVT::Other, - MVT::Flag, R20Reg, Chain); + MVT::Glue, R20Reg, Chain); Chain = SDValue(ResNode, 0); InFlag = SDValue(ResNode, 1); ReplaceUses(SDValue(Node, 0), Chain); diff --git a/lib/Target/MBlaze/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp index 2fc55c5..f39826b 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.cpp +++ b/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -35,6 +35,11 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; +static bool CC_MBlaze_AssignReg(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State); + const char *MBlazeTargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { case MBlazeISD::JmpLink : return "MBlazeISD::JmpLink"; @@ -116,8 +121,8 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM) } // Expand unsupported conversions - setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand); - setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand); + setOperationAction(ISD::BITCAST, MVT::f32, Expand); + setOperationAction(ISD::BITCAST, MVT::i32, Expand); // Expand SELECT_CC setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); @@ -170,7 +175,6 @@ MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM) // Use the default for now setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); - setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); // MBlaze doesn't have extending float->double load/store setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); @@ -208,172 +212,353 @@ SDValue MBlazeTargetLowering::LowerOperation(SDValue Op, //===----------------------------------------------------------------------===// MachineBasicBlock* MBlazeTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, - MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); - DebugLoc dl = MI->getDebugLoc(); - + MachineBasicBlock *MBB) + const { switch (MI->getOpcode()) { default: assert(false && "Unexpected instr type to insert"); + case MBlaze::ShiftRL: case MBlaze::ShiftRA: - case MBlaze::ShiftL: { - // To "insert" a shift left instruction, we actually have to insert a - // simple loop. The incoming instruction knows the destination vreg to - // set, the source vreg to operate over and the shift amount. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = BB; - ++It; - - // start: - // andi samt, samt, 31 - // beqid samt, finish - // add dst, src, r0 - // loop: - // addik samt, samt, -1 - // sra dst, dst - // bneid samt, loop - // nop - // finish: - MachineFunction *F = BB->getParent(); - MachineRegisterInfo &R = F->getRegInfo(); - MachineBasicBlock *loop = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *finish = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, loop); - F->insert(It, finish); - - // Update machine-CFG edges by transfering adding all successors and - // remaining instructions from the current block to the new block which - // will contain the Phi node for the select. - finish->splice(finish->begin(), BB, - llvm::next(MachineBasicBlock::iterator(MI)), - BB->end()); - finish->transferSuccessorsAndUpdatePHIs(BB); - - // Add the true and fallthrough blocks as its successors. - BB->addSuccessor(loop); - BB->addSuccessor(finish); - - // Next, add the finish block as a successor of the loop block - loop->addSuccessor(finish); - loop->addSuccessor(loop); - - unsigned IAMT = R.createVirtualRegister(MBlaze::GPRRegisterClass); - BuildMI(BB, dl, TII->get(MBlaze::ANDI), IAMT) - .addReg(MI->getOperand(2).getReg()) - .addImm(31); - - unsigned IVAL = R.createVirtualRegister(MBlaze::GPRRegisterClass); - BuildMI(BB, dl, TII->get(MBlaze::ADDI), IVAL) - .addReg(MI->getOperand(1).getReg()) - .addImm(0); - - BuildMI(BB, dl, TII->get(MBlaze::BEQID)) - .addReg(IAMT) - .addMBB(finish); - - unsigned DST = R.createVirtualRegister(MBlaze::GPRRegisterClass); - unsigned NDST = R.createVirtualRegister(MBlaze::GPRRegisterClass); - BuildMI(loop, dl, TII->get(MBlaze::PHI), DST) - .addReg(IVAL).addMBB(BB) - .addReg(NDST).addMBB(loop); - - unsigned SAMT = R.createVirtualRegister(MBlaze::GPRRegisterClass); - unsigned NAMT = R.createVirtualRegister(MBlaze::GPRRegisterClass); - BuildMI(loop, dl, TII->get(MBlaze::PHI), SAMT) - .addReg(IAMT).addMBB(BB) - .addReg(NAMT).addMBB(loop); - - if (MI->getOpcode() == MBlaze::ShiftL) - BuildMI(loop, dl, TII->get(MBlaze::ADD), NDST).addReg(DST).addReg(DST); - else if (MI->getOpcode() == MBlaze::ShiftRA) - BuildMI(loop, dl, TII->get(MBlaze::SRA), NDST).addReg(DST); - else if (MI->getOpcode() == MBlaze::ShiftRL) - BuildMI(loop, dl, TII->get(MBlaze::SRL), NDST).addReg(DST); - else - llvm_unreachable("Cannot lower unknown shift instruction"); - - BuildMI(loop, dl, TII->get(MBlaze::ADDI), NAMT) - .addReg(SAMT) - .addImm(-1); - - BuildMI(loop, dl, TII->get(MBlaze::BNEID)) - .addReg(NAMT) - .addMBB(loop); - - BuildMI(*finish, finish->begin(), dl, - TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) - .addReg(IVAL).addMBB(BB) - .addReg(NDST).addMBB(loop); - - // The pseudo instruction is no longer needed so remove it + case MBlaze::ShiftL: + return EmitCustomShift(MI, MBB); + + case MBlaze::Select_FCC: + case MBlaze::Select_CC: + return EmitCustomSelect(MI, MBB); + + case MBlaze::CAS32: + case MBlaze::SWP32: + case MBlaze::LAA32: + case MBlaze::LAS32: + case MBlaze::LAD32: + case MBlaze::LAO32: + case MBlaze::LAX32: + case MBlaze::LAN32: + return EmitCustomAtomic(MI, MBB); + + case MBlaze::MEMBARRIER: + // The Microblaze does not need memory barriers. Just delete the pseudo + // instruction and finish. MI->eraseFromParent(); - return finish; + return MBB; + } +} + +MachineBasicBlock* +MBlazeTargetLowering::EmitCustomShift(MachineInstr *MI, + MachineBasicBlock *MBB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + + // To "insert" a shift left instruction, we actually have to insert a + // simple loop. The incoming instruction knows the destination vreg to + // set, the source vreg to operate over and the shift amount. + const BasicBlock *LLVM_BB = MBB->getBasicBlock(); + MachineFunction::iterator It = MBB; + ++It; + + // start: + // andi samt, samt, 31 + // beqid samt, finish + // add dst, src, r0 + // loop: + // addik samt, samt, -1 + // sra dst, dst + // bneid samt, loop + // nop + // finish: + MachineFunction *F = MBB->getParent(); + MachineRegisterInfo &R = F->getRegInfo(); + MachineBasicBlock *loop = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *finish = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, loop); + F->insert(It, finish); + + // Update machine-CFG edges by transfering adding all successors and + // remaining instructions from the current block to the new block which + // will contain the Phi node for the select. + finish->splice(finish->begin(), MBB, + llvm::next(MachineBasicBlock::iterator(MI)), + MBB->end()); + finish->transferSuccessorsAndUpdatePHIs(MBB); + + // Add the true and fallthrough blocks as its successors. + MBB->addSuccessor(loop); + MBB->addSuccessor(finish); + + // Next, add the finish block as a successor of the loop block + loop->addSuccessor(finish); + loop->addSuccessor(loop); + + unsigned IAMT = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(MBB, dl, TII->get(MBlaze::ANDI), IAMT) + .addReg(MI->getOperand(2).getReg()) + .addImm(31); + + unsigned IVAL = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(MBB, dl, TII->get(MBlaze::ADDIK), IVAL) + .addReg(MI->getOperand(1).getReg()) + .addImm(0); + + BuildMI(MBB, dl, TII->get(MBlaze::BEQID)) + .addReg(IAMT) + .addMBB(finish); + + unsigned DST = R.createVirtualRegister(MBlaze::GPRRegisterClass); + unsigned NDST = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(loop, dl, TII->get(MBlaze::PHI), DST) + .addReg(IVAL).addMBB(MBB) + .addReg(NDST).addMBB(loop); + + unsigned SAMT = R.createVirtualRegister(MBlaze::GPRRegisterClass); + unsigned NAMT = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(loop, dl, TII->get(MBlaze::PHI), SAMT) + .addReg(IAMT).addMBB(MBB) + .addReg(NAMT).addMBB(loop); + + if (MI->getOpcode() == MBlaze::ShiftL) + BuildMI(loop, dl, TII->get(MBlaze::ADD), NDST).addReg(DST).addReg(DST); + else if (MI->getOpcode() == MBlaze::ShiftRA) + BuildMI(loop, dl, TII->get(MBlaze::SRA), NDST).addReg(DST); + else if (MI->getOpcode() == MBlaze::ShiftRL) + BuildMI(loop, dl, TII->get(MBlaze::SRL), NDST).addReg(DST); + else + llvm_unreachable("Cannot lower unknown shift instruction"); + + BuildMI(loop, dl, TII->get(MBlaze::ADDIK), NAMT) + .addReg(SAMT) + .addImm(-1); + + BuildMI(loop, dl, TII->get(MBlaze::BNEID)) + .addReg(NAMT) + .addMBB(loop); + + BuildMI(*finish, finish->begin(), dl, + TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) + .addReg(IVAL).addMBB(MBB) + .addReg(NDST).addMBB(loop); + + // The pseudo instruction is no longer needed so remove it + MI->eraseFromParent(); + return finish; +} + +MachineBasicBlock* +MBlazeTargetLowering::EmitCustomSelect(MachineInstr *MI, + MachineBasicBlock *MBB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + + // To "insert" a SELECT_CC instruction, we actually have to insert the + // diamond control-flow pattern. The incoming instruction knows the + // destination vreg to set, the condition code register to branch on, the + // true/false values to select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = MBB->getBasicBlock(); + MachineFunction::iterator It = MBB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // setcc r1, r2, r3 + // bNE r1, r0, copy1MBB + // fallthrough --> copy0MBB + MachineFunction *F = MBB->getParent(); + MachineBasicBlock *flsBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *dneBB = F->CreateMachineBasicBlock(LLVM_BB); + + unsigned Opc; + switch (MI->getOperand(4).getImm()) { + default: llvm_unreachable("Unknown branch condition"); + case MBlazeCC::EQ: Opc = MBlaze::BEQID; break; + case MBlazeCC::NE: Opc = MBlaze::BNEID; break; + case MBlazeCC::GT: Opc = MBlaze::BGTID; break; + case MBlazeCC::LT: Opc = MBlaze::BLTID; break; + case MBlazeCC::GE: Opc = MBlaze::BGEID; break; + case MBlazeCC::LE: Opc = MBlaze::BLEID; break; + } + + F->insert(It, flsBB); + F->insert(It, dneBB); + + // Transfer the remainder of MBB and its successor edges to dneBB. + dneBB->splice(dneBB->begin(), MBB, + llvm::next(MachineBasicBlock::iterator(MI)), + MBB->end()); + dneBB->transferSuccessorsAndUpdatePHIs(MBB); + + MBB->addSuccessor(flsBB); + MBB->addSuccessor(dneBB); + flsBB->addSuccessor(dneBB); + + BuildMI(MBB, dl, TII->get(Opc)) + .addReg(MI->getOperand(3).getReg()) + .addMBB(dneBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + //BuildMI(dneBB, dl, TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) + // .addReg(MI->getOperand(1).getReg()).addMBB(flsBB) + // .addReg(MI->getOperand(2).getReg()).addMBB(BB); + + BuildMI(*dneBB, dneBB->begin(), dl, + TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(2).getReg()).addMBB(flsBB) + .addReg(MI->getOperand(1).getReg()).addMBB(MBB); + + MI->eraseFromParent(); // The pseudo instruction is gone now. + return dneBB; +} + +MachineBasicBlock* +MBlazeTargetLowering::EmitCustomAtomic(MachineInstr *MI, + MachineBasicBlock *MBB) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + + // All atomic instructions on the Microblaze are implemented using the + // load-linked / store-conditional style atomic instruction sequences. + // Thus, all operations will look something like the following: + // + // start: + // lwx RV, RP, 0 + // <do stuff> + // swx RV, RP, 0 + // addic RC, R0, 0 + // bneid RC, start + // + // exit: + // + // To "insert" a shift left instruction, we actually have to insert a + // simple loop. The incoming instruction knows the destination vreg to + // set, the source vreg to operate over and the shift amount. + const BasicBlock *LLVM_BB = MBB->getBasicBlock(); + MachineFunction::iterator It = MBB; + ++It; + + // start: + // andi samt, samt, 31 + // beqid samt, finish + // add dst, src, r0 + // loop: + // addik samt, samt, -1 + // sra dst, dst + // bneid samt, loop + // nop + // finish: + MachineFunction *F = MBB->getParent(); + MachineRegisterInfo &R = F->getRegInfo(); + + // Create the start and exit basic blocks for the atomic operation + MachineBasicBlock *start = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exit = F->CreateMachineBasicBlock(LLVM_BB); + F->insert(It, start); + F->insert(It, exit); + + // Update machine-CFG edges by transfering adding all successors and + // remaining instructions from the current block to the new block which + // will contain the Phi node for the select. + exit->splice(exit->begin(), MBB, llvm::next(MachineBasicBlock::iterator(MI)), + MBB->end()); + exit->transferSuccessorsAndUpdatePHIs(MBB); + + // Add the fallthrough block as its successors. + MBB->addSuccessor(start); + + BuildMI(start, dl, TII->get(MBlaze::LWX), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(1).getReg()) + .addReg(MBlaze::R0); + + MachineBasicBlock *final = start; + unsigned finalReg = 0; + + switch (MI->getOpcode()) { + default: llvm_unreachable("Cannot lower unknown atomic instruction!"); + + case MBlaze::SWP32: + finalReg = MI->getOperand(2).getReg(); + start->addSuccessor(exit); + start->addSuccessor(start); + break; + + case MBlaze::LAN32: + case MBlaze::LAX32: + case MBlaze::LAO32: + case MBlaze::LAD32: + case MBlaze::LAS32: + case MBlaze::LAA32: { + unsigned opcode = 0; + switch (MI->getOpcode()) { + default: llvm_unreachable("Cannot lower unknown atomic load!"); + case MBlaze::LAA32: opcode = MBlaze::ADDIK; break; + case MBlaze::LAS32: opcode = MBlaze::RSUBIK; break; + case MBlaze::LAD32: opcode = MBlaze::AND; break; + case MBlaze::LAO32: opcode = MBlaze::OR; break; + case MBlaze::LAX32: opcode = MBlaze::XOR; break; + case MBlaze::LAN32: opcode = MBlaze::AND; break; } - case MBlaze::Select_FCC: - case MBlaze::Select_CC: { - // To "insert" a SELECT_CC instruction, we actually have to insert the - // diamond control-flow pattern. The incoming instruction knows the - // destination vreg to set, the condition code register to branch on, the - // true/false values to select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator It = BB; - ++It; - - // thisMBB: - // ... - // TrueVal = ... - // setcc r1, r2, r3 - // bNE r1, r0, copy1MBB - // fallthrough --> copy0MBB - MachineFunction *F = BB->getParent(); - MachineBasicBlock *flsBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *dneBB = F->CreateMachineBasicBlock(LLVM_BB); - - unsigned Opc; - switch (MI->getOperand(4).getImm()) { - default: llvm_unreachable("Unknown branch condition"); - case MBlazeCC::EQ: Opc = MBlaze::BNEID; break; - case MBlazeCC::NE: Opc = MBlaze::BEQID; break; - case MBlazeCC::GT: Opc = MBlaze::BLEID; break; - case MBlazeCC::LT: Opc = MBlaze::BGEID; break; - case MBlazeCC::GE: Opc = MBlaze::BLTID; break; - case MBlazeCC::LE: Opc = MBlaze::BGTID; break; + finalReg = R.createVirtualRegister(MBlaze::GPRRegisterClass); + start->addSuccessor(exit); + start->addSuccessor(start); + + BuildMI(start, dl, TII->get(opcode), finalReg) + .addReg(MI->getOperand(0).getReg()) + .addReg(MI->getOperand(2).getReg()); + + if (MI->getOpcode() == MBlaze::LAN32) { + unsigned tmp = finalReg; + finalReg = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(start, dl, TII->get(MBlaze::XORI), finalReg) + .addReg(tmp) + .addImm(-1); } + break; + } + + case MBlaze::CAS32: { + finalReg = MI->getOperand(3).getReg(); + final = F->CreateMachineBasicBlock(LLVM_BB); - F->insert(It, flsBB); - F->insert(It, dneBB); - - // Transfer the remainder of BB and its successor edges to dneBB. - dneBB->splice(dneBB->begin(), BB, - llvm::next(MachineBasicBlock::iterator(MI)), - BB->end()); - dneBB->transferSuccessorsAndUpdatePHIs(BB); - - BB->addSuccessor(flsBB); - BB->addSuccessor(dneBB); - flsBB->addSuccessor(dneBB); - - BuildMI(BB, dl, TII->get(Opc)) - .addReg(MI->getOperand(3).getReg()) - .addMBB(dneBB); - - // sinkMBB: - // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] - // ... - //BuildMI(dneBB, dl, TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) - // .addReg(MI->getOperand(1).getReg()).addMBB(flsBB) - // .addReg(MI->getOperand(2).getReg()).addMBB(BB); - - BuildMI(*dneBB, dneBB->begin(), dl, - TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) - .addReg(MI->getOperand(2).getReg()).addMBB(flsBB) - .addReg(MI->getOperand(1).getReg()).addMBB(BB); - - MI->eraseFromParent(); // The pseudo instruction is gone now. - return dneBB; + F->insert(It, final); + start->addSuccessor(exit); + start->addSuccessor(final); + final->addSuccessor(exit); + final->addSuccessor(start); + + unsigned CMP = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(start, dl, TII->get(MBlaze::CMP), CMP) + .addReg(MI->getOperand(0).getReg()) + .addReg(MI->getOperand(2).getReg()); + + BuildMI(start, dl, TII->get(MBlaze::BNEID)) + .addReg(CMP) + .addMBB(exit); + + final->moveAfter(start); + exit->moveAfter(final); + break; } } + + unsigned CHK = R.createVirtualRegister(MBlaze::GPRRegisterClass); + BuildMI(final, dl, TII->get(MBlaze::SWX)) + .addReg(finalReg) + .addReg(MI->getOperand(1).getReg()) + .addReg(MBlaze::R0); + + BuildMI(final, dl, TII->get(MBlaze::ADDIC), CHK) + .addReg(MBlaze::R0) + .addImm(0); + + BuildMI(final, dl, TII->get(MBlaze::BNEID)) + .addReg(CHK) + .addMBB(start); + + // The pseudo instruction is no longer needed so remove it + MI->eraseFromParent(); + return exit; } //===----------------------------------------------------------------------===// @@ -468,47 +653,24 @@ SDValue MBlazeTargetLowering::LowerVASTART(SDValue Op, #include "MBlazeGenCallingConv.inc" -static bool CC_MBlaze2(unsigned ValNo, MVT ValVT, - MVT LocVT, CCValAssign::LocInfo LocInfo, - ISD::ArgFlagsTy ArgFlags, CCState &State) { - static const unsigned RegsSize=6; - static const unsigned IntRegs[] = { +static bool CC_MBlaze_AssignReg(unsigned &ValNo, MVT &ValVT, MVT &LocVT, + CCValAssign::LocInfo &LocInfo, + ISD::ArgFlagsTy &ArgFlags, + CCState &State) { + static const unsigned ArgRegs[] = { MBlaze::R5, MBlaze::R6, MBlaze::R7, MBlaze::R8, MBlaze::R9, MBlaze::R10 }; - unsigned Reg=0; - - // Promote i8 and i16 - if (LocVT == MVT::i8 || LocVT == MVT::i16) { - LocVT = MVT::i32; - if (ArgFlags.isSExt()) - LocInfo = CCValAssign::SExt; - else if (ArgFlags.isZExt()) - LocInfo = CCValAssign::ZExt; - else - LocInfo = CCValAssign::AExt; - } - - if (ValVT == MVT::i32) { - Reg = State.AllocateReg(IntRegs, RegsSize); - LocVT = MVT::i32; - } else if (ValVT == MVT::f32) { - Reg = State.AllocateReg(IntRegs, RegsSize); - LocVT = MVT::f32; - } + const unsigned NumArgRegs = array_lengthof(ArgRegs); + unsigned Reg = State.AllocateReg(ArgRegs, NumArgRegs); + if (!Reg) return false; - if (!Reg) { - unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; - unsigned Offset = State.AllocateStack(SizeInBytes, SizeInBytes); - State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); - } else { - unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; - State.AllocateStack(SizeInBytes, SizeInBytes); - State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - } + unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; + State.AllocateStack(SizeInBytes, SizeInBytes); + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - return false; // CC must always match + return true; } //===----------------------------------------------------------------------===// @@ -529,27 +691,31 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, // MBlaze does not yet support tail call optimization isTailCall = false; + // The MBlaze requires stack slots for arguments passed to var arg + // functions even if they are passed in registers. + bool needsRegArgSlots = isVarArg; + MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); + const TargetFrameLowering &TFI = *MF.getTarget().getFrameLowering(); // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); - CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze2); + CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze); // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = CCInfo.getNextStackOffset(); + + // Variable argument function calls require a minimum of 24-bytes of stack + if (isVarArg && NumBytes < 24) NumBytes = 24; + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; SmallVector<SDValue, 8> MemOpChains; - // First/LastArgStackLoc contains the first/last - // "at stack" argument location. - int LastArgStackLoc = 0; - unsigned FirstStackArgLoc = 0; - // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -579,10 +745,15 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, // Register can't get to this point... assert(VA.isMemLoc()); + // Since we are alread passing values on the stack we don't + // need to worry about creating additional slots for the + // values passed via registers. + needsRegArgSlots = false; + // Create the frame index object for this incoming parameter - LastArgStackLoc = (FirstStackArgLoc + VA.getLocMemOffset()); - int FI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8, - LastArgStackLoc, true); + unsigned ArgSize = VA.getValVT().getSizeInBits()/8; + unsigned StackLoc = VA.getLocMemOffset() + 4; + int FI = MFI->CreateFixedObject(ArgSize, StackLoc, true); SDValue PtrOff = DAG.getFrameIndex(FI,getPointerTy()); @@ -594,6 +765,11 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, } } + // If we need to reserve stack space for the arguments passed via registers + // then create a fixed stack object at the beginning of the stack. + if (needsRegArgSlots && TFI.hasReservedCallFrame(MF)) + MFI->CreateFixedObject(28,0,true); + // Transform all store nodes into one single node because all store // nodes are independent of each other. if (!MemOpChains.empty()) @@ -625,7 +801,7 @@ LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, // = Chain, Callee, Reg#1, Reg#2, ... // // Returns a chain & a flag for retval copy to use. - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); SmallVector<SDValue, 8> Ops; Ops.push_back(Chain); Ops.push_back(Callee); @@ -710,11 +886,9 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); - CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze2); + CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze); SDValue StackPtr; - unsigned FirstStackArgLoc = 0; - for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; @@ -753,9 +927,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, } InVals.push_back(ArgValue); - } else { // VA.isRegLoc() - // sanity check assert(VA.isMemLoc()); @@ -771,9 +943,10 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, // offset on PEI::calculateFrameObjectOffsets. // Arguments are always 32-bit. unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; + unsigned StackLoc = VA.getLocMemOffset() + 4; int FI = MFI->CreateFixedObject(ArgSize, 0, true); - MBlazeFI->recordLoadArgsFI(FI, -(ArgSize+ - (FirstStackArgLoc + VA.getLocMemOffset()))); + MBlazeFI->recordLoadArgsFI(FI, -StackLoc); + MBlazeFI->recordLiveIn(FI); // Create load nodes to retrieve arguments from the stack SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); @@ -796,7 +969,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, unsigned Begin = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R5); unsigned Start = MBlazeRegisterInfo::getRegisterNumbering(ArgRegEnd+1); unsigned End = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R10); - unsigned StackLoc = ArgLocs.size()-1 + (Start - Begin); + unsigned StackLoc = Start - Begin + 1; for (; Start <= End; ++Start, ++StackLoc) { unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start); @@ -804,7 +977,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32); int FI = MFI->CreateFixedObject(4, 0, true); - MBlazeFI->recordStoreVarArgsFI(FI, -(4+(StackLoc*4))); + MBlazeFI->recordStoreVarArgsFI(FI, -(StackLoc*4)); SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, MachinePointerInfo(), @@ -871,13 +1044,18 @@ LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, Flag = Chain.getValue(1); } - // Return on MBlaze is always a "rtsd R15, 8" + // If this function is using the interrupt_handler calling convention + // then use "rtid r14, 0" otherwise use "rtsd r15, 8" + unsigned Ret = (CallConv == llvm::CallingConv::MBLAZE_INTR) ? MBlazeISD::IRet + : MBlazeISD::Ret; + unsigned Reg = (CallConv == llvm::CallingConv::MBLAZE_INTR) ? MBlaze::R14 + : MBlaze::R15; + SDValue DReg = DAG.getRegister(Reg, MVT::i32); + if (Flag.getNode()) - return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other, - Chain, DAG.getRegister(MBlaze::R15, MVT::i32), Flag); - else // Return Void - return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other, - Chain, DAG.getRegister(MBlaze::R15, MVT::i32)); + return DAG.getNode(Ret, dl, MVT::Other, Chain, DReg, Flag); + + return DAG.getNode(Ret, dl, MVT::Other, Chain, DReg); } //===----------------------------------------------------------------------===// @@ -926,8 +1104,8 @@ MBlazeTargetLowering::getSingleConstraintMatchWeight( default: weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); break;
- case 'd': - case 'y': + case 'd': + case 'y': if (type->isIntegerTy()) weight = CW_Register; break; diff --git a/lib/Target/MBlaze/MBlazeISelLowering.h b/lib/Target/MBlaze/MBlazeISelLowering.h index 4f09851..91649bc 100644 --- a/lib/Target/MBlaze/MBlazeISelLowering.h +++ b/lib/Target/MBlaze/MBlazeISelLowering.h @@ -78,8 +78,11 @@ namespace llvm { // Integer Compare ICmp, - // Return - Ret + // Return from subroutine + Ret, + + // Return from interrupt + IRet }; } @@ -146,6 +149,15 @@ namespace llvm { const SmallVectorImpl<SDValue> &OutVals, DebugLoc dl, SelectionDAG &DAG) const; + virtual MachineBasicBlock* + EmitCustomShift(MachineInstr *MI, MachineBasicBlock *MBB) const; + + virtual MachineBasicBlock* + EmitCustomSelect(MachineInstr *MI, MachineBasicBlock *MBB) const; + + virtual MachineBasicBlock* + EmitCustomAtomic(MachineInstr *MI, MachineBasicBlock *MBB) const; + virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; diff --git a/lib/Target/MBlaze/MBlazeInstrFPU.td b/lib/Target/MBlaze/MBlazeInstrFPU.td index 8f37332..094de5c 100644 --- a/lib/Target/MBlaze/MBlazeInstrFPU.td +++ b/lib/Target/MBlaze/MBlazeInstrFPU.td @@ -143,74 +143,74 @@ let Predicates=[HasFPU] in { // SET_CC operations let Predicates=[HasFPU] in { def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETEQ), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_EQ GPR:$L, GPR:$R), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETNE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_EQ GPR:$L, GPR:$R), 1)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOEQ), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_EQ GPR:$L, GPR:$R), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETONE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (XOR (FCMP_UN GPR:$L, GPR:$R), (FCMP_EQ GPR:$L, GPR:$R)), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETONE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (OR (FCMP_UN GPR:$L, GPR:$R), (FCMP_EQ GPR:$L, GPR:$R)), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETGT), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_GT GPR:$L, GPR:$R), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETLT), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_LT GPR:$L, GPR:$R), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETGE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_GE GPR:$L, GPR:$R), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETLE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_LE GPR:$L, GPR:$R), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOGT), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_GT GPR:$L, GPR:$R), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOLT), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_LT GPR:$L, GPR:$R), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOGE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_GE GPR:$L, GPR:$R), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETOLE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_LE GPR:$L, GPR:$R), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUEQ), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (OR (FCMP_UN GPR:$L, GPR:$R), (FCMP_EQ GPR:$L, GPR:$R)), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUNE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_NE GPR:$L, GPR:$R), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUGT), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (OR (FCMP_UN GPR:$L, GPR:$R), (FCMP_GT GPR:$L, GPR:$R)), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETULT), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (OR (FCMP_UN GPR:$L, GPR:$R), (FCMP_LT GPR:$L, GPR:$R)), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUGE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (OR (FCMP_UN GPR:$L, GPR:$R), (FCMP_GE GPR:$L, GPR:$R)), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETULE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (OR (FCMP_UN GPR:$L, GPR:$R), (FCMP_LE GPR:$L, GPR:$R)), 2)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETO), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_UN GPR:$L, GPR:$R), 1)>; def : Pat<(setcc (f32 GPR:$L), (f32 GPR:$R), SETUO), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), (FCMP_UN GPR:$L, GPR:$R), 2)>; } diff --git a/lib/Target/MBlaze/MBlazeInstrFSL.td b/lib/Target/MBlaze/MBlazeInstrFSL.td index 0bdd02c..3209845 100644 --- a/lib/Target/MBlaze/MBlazeInstrFSL.td +++ b/lib/Target/MBlaze/MBlazeInstrFSL.td @@ -115,14 +115,6 @@ def EGET : FSLGet<0x1B, 0x01, "eget ", int_mblaze_fsl_eget>; def EAGET : FSLGet<0x1B, 0x03, "eaget ", int_mblaze_fsl_eaget>; def ECGET : FSLGet<0x1B, 0x09, "ecget ", int_mblaze_fsl_ecget>; def ECAGET : FSLGet<0x1B, 0x0B, "ecaget ", int_mblaze_fsl_ecaget>; -def NGET : FSLGet<0x1B, 0x10, "nget ", int_mblaze_fsl_nget>; -def NAGET : FSLGet<0x1B, 0x12, "naget ", int_mblaze_fsl_naget>; -def NCGET : FSLGet<0x1B, 0x18, "ncget ", int_mblaze_fsl_ncget>; -def NCAGET : FSLGet<0x1B, 0x1A, "ncaget ", int_mblaze_fsl_ncaget>; -def NEGET : FSLGet<0x1B, 0x11, "neget ", int_mblaze_fsl_neget>; -def NEAGET : FSLGet<0x1B, 0x13, "neaget ", int_mblaze_fsl_neaget>; -def NECGET : FSLGet<0x1B, 0x19, "necget ", int_mblaze_fsl_necget>; -def NECAGET : FSLGet<0x1B, 0x1B, "necaget ", int_mblaze_fsl_necaget>; def TGET : FSLGet<0x1B, 0x04, "tget ", int_mblaze_fsl_tget>; def TAGET : FSLGet<0x1B, 0x06, "taget ", int_mblaze_fsl_taget>; def TCGET : FSLGet<0x1B, 0x0C, "tcget ", int_mblaze_fsl_tcget>; @@ -131,14 +123,25 @@ def TEGET : FSLGet<0x1B, 0x05, "teget ", int_mblaze_fsl_teget>; def TEAGET : FSLGet<0x1B, 0x07, "teaget ", int_mblaze_fsl_teaget>; def TECGET : FSLGet<0x1B, 0x0D, "tecget ", int_mblaze_fsl_tecget>; def TECAGET : FSLGet<0x1B, 0x0F, "tecaget ", int_mblaze_fsl_tecaget>; -def TNGET : FSLGet<0x1B, 0x14, "tnget ", int_mblaze_fsl_tnget>; -def TNAGET : FSLGet<0x1B, 0x16, "tnaget ", int_mblaze_fsl_tnaget>; -def TNCGET : FSLGet<0x1B, 0x1C, "tncget ", int_mblaze_fsl_tncget>; -def TNCAGET : FSLGet<0x1B, 0x1E, "tncaget ", int_mblaze_fsl_tncaget>; -def TNEGET : FSLGet<0x1B, 0x15, "tneget ", int_mblaze_fsl_tneget>; -def TNEAGET : FSLGet<0x1B, 0x17, "tneaget ", int_mblaze_fsl_tneaget>; -def TNECGET : FSLGet<0x1B, 0x1D, "tnecget ", int_mblaze_fsl_tnecget>; -def TNECAGET : FSLGet<0x1B, 0x1F, "tnecaget ", int_mblaze_fsl_tnecaget>; + +let Defs = [CARRY] in { + def NGET : FSLGet<0x1B, 0x10, "nget ", int_mblaze_fsl_nget>; + def NAGET : FSLGet<0x1B, 0x12, "naget ", int_mblaze_fsl_naget>; + def NCGET : FSLGet<0x1B, 0x18, "ncget ", int_mblaze_fsl_ncget>; + def NCAGET : FSLGet<0x1B, 0x1A, "ncaget ", int_mblaze_fsl_ncaget>; + def NEGET : FSLGet<0x1B, 0x11, "neget ", int_mblaze_fsl_neget>; + def NEAGET : FSLGet<0x1B, 0x13, "neaget ", int_mblaze_fsl_neaget>; + def NECGET : FSLGet<0x1B, 0x19, "necget ", int_mblaze_fsl_necget>; + def NECAGET : FSLGet<0x1B, 0x1B, "necaget ", int_mblaze_fsl_necaget>; + def TNGET : FSLGet<0x1B, 0x14, "tnget ", int_mblaze_fsl_tnget>; + def TNAGET : FSLGet<0x1B, 0x16, "tnaget ", int_mblaze_fsl_tnaget>; + def TNCGET : FSLGet<0x1B, 0x1C, "tncget ", int_mblaze_fsl_tncget>; + def TNCAGET : FSLGet<0x1B, 0x1E, "tncaget ", int_mblaze_fsl_tncaget>; + def TNEGET : FSLGet<0x1B, 0x15, "tneget ", int_mblaze_fsl_tneget>; + def TNEAGET : FSLGet<0x1B, 0x17, "tneaget ", int_mblaze_fsl_tneaget>; + def TNECGET : FSLGet<0x1B, 0x1D, "tnecget ", int_mblaze_fsl_tnecget>; + def TNECAGET : FSLGet<0x1B, 0x1F, "tnecaget ", int_mblaze_fsl_tnecaget>; +} //===----------------------------------------------------------------------===// // FSL Dynamic Get Instructions @@ -151,14 +154,6 @@ def EGETD : FSLGetD<0x13, 0x01, "egetd ", int_mblaze_fsl_eget>; def EAGETD : FSLGetD<0x13, 0x03, "eagetd ", int_mblaze_fsl_eaget>; def ECGETD : FSLGetD<0x13, 0x09, "ecgetd ", int_mblaze_fsl_ecget>; def ECAGETD : FSLGetD<0x13, 0x0B, "ecagetd ", int_mblaze_fsl_ecaget>; -def NGETD : FSLGetD<0x13, 0x10, "ngetd ", int_mblaze_fsl_nget>; -def NAGETD : FSLGetD<0x13, 0x12, "nagetd ", int_mblaze_fsl_naget>; -def NCGETD : FSLGetD<0x13, 0x18, "ncgetd ", int_mblaze_fsl_ncget>; -def NCAGETD : FSLGetD<0x13, 0x1A, "ncagetd ", int_mblaze_fsl_ncaget>; -def NEGETD : FSLGetD<0x13, 0x11, "negetd ", int_mblaze_fsl_neget>; -def NEAGETD : FSLGetD<0x13, 0x13, "neagetd ", int_mblaze_fsl_neaget>; -def NECGETD : FSLGetD<0x13, 0x19, "necgetd ", int_mblaze_fsl_necget>; -def NECAGETD : FSLGetD<0x13, 0x1B, "necagetd ", int_mblaze_fsl_necaget>; def TGETD : FSLGetD<0x13, 0x04, "tgetd ", int_mblaze_fsl_tget>; def TAGETD : FSLGetD<0x13, 0x06, "tagetd ", int_mblaze_fsl_taget>; def TCGETD : FSLGetD<0x13, 0x0C, "tcgetd ", int_mblaze_fsl_tcget>; @@ -167,14 +162,25 @@ def TEGETD : FSLGetD<0x13, 0x05, "tegetd ", int_mblaze_fsl_teget>; def TEAGETD : FSLGetD<0x13, 0x07, "teagetd ", int_mblaze_fsl_teaget>; def TECGETD : FSLGetD<0x13, 0x0D, "tecgetd ", int_mblaze_fsl_tecget>; def TECAGETD : FSLGetD<0x13, 0x0F, "tecagetd ", int_mblaze_fsl_tecaget>; -def TNGETD : FSLGetD<0x13, 0x14, "tngetd ", int_mblaze_fsl_tnget>; -def TNAGETD : FSLGetD<0x13, 0x16, "tnagetd ", int_mblaze_fsl_tnaget>; -def TNCGETD : FSLGetD<0x13, 0x1C, "tncgetd ", int_mblaze_fsl_tncget>; -def TNCAGETD : FSLGetD<0x13, 0x1E, "tncagetd ", int_mblaze_fsl_tncaget>; -def TNEGETD : FSLGetD<0x13, 0x15, "tnegetd ", int_mblaze_fsl_tneget>; -def TNEAGETD : FSLGetD<0x13, 0x17, "tneagetd ", int_mblaze_fsl_tneaget>; -def TNECGETD : FSLGetD<0x13, 0x1D, "tnecgetd ", int_mblaze_fsl_tnecget>; -def TNECAGETD : FSLGetD<0x13, 0x1F, "tnecagetd", int_mblaze_fsl_tnecaget>; + +let Defs = [CARRY] in { + def NGETD : FSLGetD<0x13, 0x10, "ngetd ", int_mblaze_fsl_nget>; + def NAGETD : FSLGetD<0x13, 0x12, "nagetd ", int_mblaze_fsl_naget>; + def NCGETD : FSLGetD<0x13, 0x18, "ncgetd ", int_mblaze_fsl_ncget>; + def NCAGETD : FSLGetD<0x13, 0x1A, "ncagetd ", int_mblaze_fsl_ncaget>; + def NEGETD : FSLGetD<0x13, 0x11, "negetd ", int_mblaze_fsl_neget>; + def NEAGETD : FSLGetD<0x13, 0x13, "neagetd ", int_mblaze_fsl_neaget>; + def NECGETD : FSLGetD<0x13, 0x19, "necgetd ", int_mblaze_fsl_necget>; + def NECAGETD : FSLGetD<0x13, 0x1B, "necagetd ", int_mblaze_fsl_necaget>; + def TNGETD : FSLGetD<0x13, 0x14, "tngetd ", int_mblaze_fsl_tnget>; + def TNAGETD : FSLGetD<0x13, 0x16, "tnagetd ", int_mblaze_fsl_tnaget>; + def TNCGETD : FSLGetD<0x13, 0x1C, "tncgetd ", int_mblaze_fsl_tncget>; + def TNCAGETD : FSLGetD<0x13, 0x1E, "tncagetd ", int_mblaze_fsl_tncaget>; + def TNEGETD : FSLGetD<0x13, 0x15, "tnegetd ", int_mblaze_fsl_tneget>; + def TNEAGETD : FSLGetD<0x13, 0x17, "tneagetd ", int_mblaze_fsl_tneaget>; + def TNECGETD : FSLGetD<0x13, 0x1D, "tnecgetd ", int_mblaze_fsl_tnecget>; + def TNECAGETD : FSLGetD<0x13, 0x1F, "tnecagetd", int_mblaze_fsl_tnecaget>; +} //===----------------------------------------------------------------------===// // FSL Put Instructions @@ -183,18 +189,21 @@ def PUT : FSLPut<0x1B, 0x0, "put ", int_mblaze_fsl_put>; def APUT : FSLPut<0x1B, 0x1, "aput ", int_mblaze_fsl_aput>; def CPUT : FSLPut<0x1B, 0x4, "cput ", int_mblaze_fsl_cput>; def CAPUT : FSLPut<0x1B, 0x5, "caput ", int_mblaze_fsl_caput>; -def NPUT : FSLPut<0x1B, 0x8, "nput ", int_mblaze_fsl_nput>; -def NAPUT : FSLPut<0x1B, 0x9, "naput ", int_mblaze_fsl_naput>; -def NCPUT : FSLPut<0x1B, 0xC, "ncput ", int_mblaze_fsl_ncput>; -def NCAPUT : FSLPut<0x1B, 0xD, "ncaput ", int_mblaze_fsl_ncaput>; def TPUT : FSLPutT<0x1B, 0x2, "tput ", int_mblaze_fsl_tput>; def TAPUT : FSLPutT<0x1B, 0x3, "taput ", int_mblaze_fsl_taput>; def TCPUT : FSLPutT<0x1B, 0x6, "tcput ", int_mblaze_fsl_tcput>; def TCAPUT : FSLPutT<0x1B, 0x7, "tcaput ", int_mblaze_fsl_tcaput>; -def TNPUT : FSLPutT<0x1B, 0xA, "tnput ", int_mblaze_fsl_tnput>; -def TNAPUT : FSLPutT<0x1B, 0xB, "tnaput ", int_mblaze_fsl_tnaput>; -def TNCPUT : FSLPutT<0x1B, 0xE, "tncput ", int_mblaze_fsl_tncput>; -def TNCAPUT : FSLPutT<0x1B, 0xF, "tncaput ", int_mblaze_fsl_tncaput>; + +let Defs = [CARRY] in { + def NPUT : FSLPut<0x1B, 0x8, "nput ", int_mblaze_fsl_nput>; + def NAPUT : FSLPut<0x1B, 0x9, "naput ", int_mblaze_fsl_naput>; + def NCPUT : FSLPut<0x1B, 0xC, "ncput ", int_mblaze_fsl_ncput>; + def NCAPUT : FSLPut<0x1B, 0xD, "ncaput ", int_mblaze_fsl_ncaput>; + def TNPUT : FSLPutT<0x1B, 0xA, "tnput ", int_mblaze_fsl_tnput>; + def TNAPUT : FSLPutT<0x1B, 0xB, "tnaput ", int_mblaze_fsl_tnaput>; + def TNCPUT : FSLPutT<0x1B, 0xE, "tncput ", int_mblaze_fsl_tncput>; + def TNCAPUT : FSLPutT<0x1B, 0xF, "tncaput ", int_mblaze_fsl_tncaput>; +} //===----------------------------------------------------------------------===// // FSL Dynamic Put Instructions @@ -203,15 +212,18 @@ def PUTD : FSLPutD<0x13, 0x0, "putd ", int_mblaze_fsl_put>; def APUTD : FSLPutD<0x13, 0x1, "aputd ", int_mblaze_fsl_aput>; def CPUTD : FSLPutD<0x13, 0x4, "cputd ", int_mblaze_fsl_cput>; def CAPUTD : FSLPutD<0x13, 0x5, "caputd ", int_mblaze_fsl_caput>; -def NPUTD : FSLPutD<0x13, 0x8, "nputd ", int_mblaze_fsl_nput>; -def NAPUTD : FSLPutD<0x13, 0x9, "naputd ", int_mblaze_fsl_naput>; -def NCPUTD : FSLPutD<0x13, 0xC, "ncputd ", int_mblaze_fsl_ncput>; -def NCAPUTD : FSLPutD<0x13, 0xD, "ncaputd ", int_mblaze_fsl_ncaput>; def TPUTD : FSLPutTD<0x13, 0x2, "tputd ", int_mblaze_fsl_tput>; def TAPUTD : FSLPutTD<0x13, 0x3, "taputd ", int_mblaze_fsl_taput>; def TCPUTD : FSLPutTD<0x13, 0x6, "tcputd ", int_mblaze_fsl_tcput>; def TCAPUTD : FSLPutTD<0x13, 0x7, "tcaputd ", int_mblaze_fsl_tcaput>; -def TNPUTD : FSLPutTD<0x13, 0xA, "tnputd ", int_mblaze_fsl_tnput>; -def TNAPUTD : FSLPutTD<0x13, 0xB, "tnaputd ", int_mblaze_fsl_tnaput>; -def TNCPUTD : FSLPutTD<0x13, 0xE, "tncputd ", int_mblaze_fsl_tncput>; -def TNCAPUTD : FSLPutTD<0x13, 0xF, "tncaputd ", int_mblaze_fsl_tncaput>; + +let Defs = [CARRY] in { + def NPUTD : FSLPutD<0x13, 0x8, "nputd ", int_mblaze_fsl_nput>; + def NAPUTD : FSLPutD<0x13, 0x9, "naputd ", int_mblaze_fsl_naput>; + def NCPUTD : FSLPutD<0x13, 0xC, "ncputd ", int_mblaze_fsl_ncput>; + def NCAPUTD : FSLPutD<0x13, 0xD, "ncaputd ", int_mblaze_fsl_ncaput>; + def TNPUTD : FSLPutTD<0x13, 0xA, "tnputd ", int_mblaze_fsl_tnput>; + def TNAPUTD : FSLPutTD<0x13, 0xB, "tnaputd ", int_mblaze_fsl_tnaput>; + def TNCPUTD : FSLPutTD<0x13, 0xE, "tncputd ", int_mblaze_fsl_tncput>; + def TNCAPUTD : FSLPutTD<0x13, 0xF, "tncaputd ", int_mblaze_fsl_tncaput>; +} diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.cpp b/lib/Target/MBlaze/MBlazeInstrInfo.cpp index 10bba97..b353dcd 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.cpp +++ b/lib/Target/MBlaze/MBlazeInstrInfo.cpp @@ -80,7 +80,7 @@ copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const { - llvm::BuildMI(MBB, I, DL, get(MBlaze::ADD), DestReg) + llvm::BuildMI(MBB, I, DL, get(MBlaze::ADDK), DestReg) .addReg(SrcReg, getKillRegState(KillSrc)).addReg(MBlaze::R0); } @@ -107,15 +107,162 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, //===----------------------------------------------------------------------===// // Branch Analysis //===----------------------------------------------------------------------===// +bool MBlazeInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl<MachineOperand> &Cond, + bool AllowModify) const { + // If the block has no terminators, it just falls into the block after it. + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) + return false; + --I; + while (I->isDebugValue()) { + if (I == MBB.begin()) + return false; + --I; + } + if (!isUnpredicatedTerminator(I)) + return false; + + // Get the last instruction in the block. + MachineInstr *LastInst = I; + + // If there is only one terminator instruction, process it. + unsigned LastOpc = LastInst->getOpcode(); + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { + if (MBlaze::isUncondBranchOpcode(LastOpc)) { + TBB = LastInst->getOperand(0).getMBB(); + return false; + } + if (MBlaze::isCondBranchOpcode(LastOpc)) { + // Block ends with fall-through condbranch. + TBB = LastInst->getOperand(1).getMBB(); + Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); + Cond.push_back(LastInst->getOperand(0)); + return false; + } + // Otherwise, don't know what this is. + return true; + } + + // Get the instruction before it if it's a terminator. + MachineInstr *SecondLastInst = I; + + // If there are three terminators, we don't know what sort of block this is. + if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I)) + return true; + + // If the block ends with something like BEQID then BRID, handle it. + if (MBlaze::isCondBranchOpcode(SecondLastInst->getOpcode()) && + MBlaze::isUncondBranchOpcode(LastInst->getOpcode())) { + TBB = SecondLastInst->getOperand(1).getMBB(); + Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode())); + Cond.push_back(SecondLastInst->getOperand(0)); + FBB = LastInst->getOperand(0).getMBB(); + return false; + } + + // If the block ends with two unconditional branches, handle it. + // The second one is not executed, so remove it. + if (MBlaze::isUncondBranchOpcode(SecondLastInst->getOpcode()) && + MBlaze::isUncondBranchOpcode(LastInst->getOpcode())) { + TBB = SecondLastInst->getOperand(0).getMBB(); + I = LastInst; + if (AllowModify) + I->eraseFromParent(); + return false; + } + + // Otherwise, can't handle this. + return true; +} + unsigned MBlazeInstrInfo:: InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, const SmallVectorImpl<MachineOperand> &Cond, DebugLoc DL) const { - // Can only insert uncond branches so far. - assert(Cond.empty() && !FBB && TBB && "Can only handle uncond branches!"); - BuildMI(&MBB, DL, get(MBlaze::BRI)).addMBB(TBB); - return 1; + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + assert((Cond.size() == 2 || Cond.size() == 0) && + "MBlaze branch conditions have two components!"); + + unsigned Opc = MBlaze::BRID; + if (!Cond.empty()) + Opc = (unsigned)Cond[0].getImm(); + + if (FBB == 0) { + if (Cond.empty()) // Unconditional branch + BuildMI(&MBB, DL, get(Opc)).addMBB(TBB); + else // Conditional branch + BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()).addMBB(TBB); + return 1; + } + + BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()).addMBB(TBB); + BuildMI(&MBB, DL, get(MBlaze::BRID)).addMBB(FBB); + return 2; +} + +unsigned MBlazeInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) return 0; + --I; + while (I->isDebugValue()) { + if (I == MBB.begin()) + return 0; + --I; + } + + if (!MBlaze::isUncondBranchOpcode(I->getOpcode()) && + !MBlaze::isCondBranchOpcode(I->getOpcode())) + return 0; + + // Remove the branch. + I->eraseFromParent(); + + I = MBB.end(); + + if (I == MBB.begin()) return 1; + --I; + if (!MBlaze::isCondBranchOpcode(I->getOpcode())) + return 1; + + // Remove the branch. + I->eraseFromParent(); + return 2; +} + +bool MBlazeInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { + assert(Cond.size() == 2 && "Invalid MBlaze branch opcode!"); + switch (Cond[0].getImm()) { + default: return true; + case MBlaze::BEQ: Cond[0].setImm(MBlaze::BNE); return false; + case MBlaze::BNE: Cond[0].setImm(MBlaze::BEQ); return false; + case MBlaze::BGT: Cond[0].setImm(MBlaze::BLE); return false; + case MBlaze::BGE: Cond[0].setImm(MBlaze::BLT); return false; + case MBlaze::BLT: Cond[0].setImm(MBlaze::BGE); return false; + case MBlaze::BLE: Cond[0].setImm(MBlaze::BGT); return false; + case MBlaze::BEQI: Cond[0].setImm(MBlaze::BNEI); return false; + case MBlaze::BNEI: Cond[0].setImm(MBlaze::BEQI); return false; + case MBlaze::BGTI: Cond[0].setImm(MBlaze::BLEI); return false; + case MBlaze::BGEI: Cond[0].setImm(MBlaze::BLTI); return false; + case MBlaze::BLTI: Cond[0].setImm(MBlaze::BGEI); return false; + case MBlaze::BLEI: Cond[0].setImm(MBlaze::BGTI); return false; + case MBlaze::BEQD: Cond[0].setImm(MBlaze::BNED); return false; + case MBlaze::BNED: Cond[0].setImm(MBlaze::BEQD); return false; + case MBlaze::BGTD: Cond[0].setImm(MBlaze::BLED); return false; + case MBlaze::BGED: Cond[0].setImm(MBlaze::BLTD); return false; + case MBlaze::BLTD: Cond[0].setImm(MBlaze::BGED); return false; + case MBlaze::BLED: Cond[0].setImm(MBlaze::BGTD); return false; + case MBlaze::BEQID: Cond[0].setImm(MBlaze::BNEID); return false; + case MBlaze::BNEID: Cond[0].setImm(MBlaze::BEQID); return false; + case MBlaze::BGTID: Cond[0].setImm(MBlaze::BLEID); return false; + case MBlaze::BGEID: Cond[0].setImm(MBlaze::BLTID); return false; + case MBlaze::BLTID: Cond[0].setImm(MBlaze::BGEID); return false; + case MBlaze::BLEID: Cond[0].setImm(MBlaze::BGTID); return false; + } } /// getGlobalBaseReg - Return a virtual register initialized with the diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.h b/lib/Target/MBlaze/MBlazeInstrInfo.h index af1842f..b7300c1 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.h +++ b/lib/Target/MBlaze/MBlazeInstrInfo.h @@ -73,59 +73,92 @@ namespace MBlaze { FCOND_GT, // Only integer conditions - COND_E, - COND_GZ, - COND_GEZ, - COND_LZ, - COND_LEZ, + COND_EQ, + COND_GT, + COND_GE, + COND_LT, + COND_LE, COND_NE, COND_INVALID }; // Turn condition code into conditional branch opcode. - unsigned GetCondBranchFromCond(CondCode CC); + inline static unsigned GetCondBranchFromCond(CondCode CC) { + switch (CC) { + default: llvm_unreachable("Unknown condition code"); + case COND_EQ: return MBlaze::BEQID; + case COND_NE: return MBlaze::BNEID; + case COND_GT: return MBlaze::BGTID; + case COND_GE: return MBlaze::BGEID; + case COND_LT: return MBlaze::BLTID; + case COND_LE: return MBlaze::BLEID; + } + } /// GetOppositeBranchCondition - Return the inverse of the specified cond, /// e.g. turning COND_E to COND_NE. - CondCode GetOppositeBranchCondition(MBlaze::CondCode CC); + // CondCode GetOppositeBranchCondition(MBlaze::CondCode CC); /// MBlazeCCToString - Map each FP condition code to its string - inline static const char *MBlazeFCCToString(MBlaze::CondCode CC) - { + inline static const char *MBlazeFCCToString(MBlaze::CondCode CC) { switch (CC) { - default: llvm_unreachable("Unknown condition code"); - case FCOND_F: - case FCOND_T: return "f"; - case FCOND_UN: - case FCOND_OR: return "un"; - case FCOND_EQ: - case FCOND_NEQ: return "eq"; - case FCOND_UEQ: - case FCOND_OGL: return "ueq"; - case FCOND_OLT: - case FCOND_UGE: return "olt"; - case FCOND_ULT: - case FCOND_OGE: return "ult"; - case FCOND_OLE: - case FCOND_UGT: return "ole"; - case FCOND_ULE: - case FCOND_OGT: return "ule"; - case FCOND_SF: - case FCOND_ST: return "sf"; - case FCOND_NGLE: - case FCOND_GLE: return "ngle"; - case FCOND_SEQ: - case FCOND_SNE: return "seq"; - case FCOND_NGL: - case FCOND_GL: return "ngl"; - case FCOND_LT: - case FCOND_NLT: return "lt"; - case FCOND_NGE: - case FCOND_GE: return "ge"; - case FCOND_LE: - case FCOND_NLE: return "nle"; - case FCOND_NGT: - case FCOND_GT: return "gt"; + default: llvm_unreachable("Unknown condition code"); + case FCOND_F: + case FCOND_T: return "f"; + case FCOND_UN: + case FCOND_OR: return "un"; + case FCOND_EQ: + case FCOND_NEQ: return "eq"; + case FCOND_UEQ: + case FCOND_OGL: return "ueq"; + case FCOND_OLT: + case FCOND_UGE: return "olt"; + case FCOND_ULT: + case FCOND_OGE: return "ult"; + case FCOND_OLE: + case FCOND_UGT: return "ole"; + case FCOND_ULE: + case FCOND_OGT: return "ule"; + case FCOND_SF: + case FCOND_ST: return "sf"; + case FCOND_NGLE: + case FCOND_GLE: return "ngle"; + case FCOND_SEQ: + case FCOND_SNE: return "seq"; + case FCOND_NGL: + case FCOND_GL: return "ngl"; + case FCOND_LT: + case FCOND_NLT: return "lt"; + case FCOND_NGE: + case FCOND_GE: return "ge"; + case FCOND_LE: + case FCOND_NLE: return "nle"; + case FCOND_NGT: + case FCOND_GT: return "gt"; + } + } + + inline static bool isUncondBranchOpcode(int Opc) { + switch (Opc) { + default: return false; + case MBlaze::BRI: + case MBlaze::BRAI: + case MBlaze::BRID: + case MBlaze::BRAID: + return true; + } + } + + inline static bool isCondBranchOpcode(int Opc) { + switch (Opc) { + default: return false; + case MBlaze::BEQI: case MBlaze::BEQID: + case MBlaze::BNEI: case MBlaze::BNEID: + case MBlaze::BGTI: case MBlaze::BGTID: + case MBlaze::BGEI: case MBlaze::BGEID: + case MBlaze::BLTI: case MBlaze::BLTID: + case MBlaze::BLEI: case MBlaze::BLEID: + return true; } } } @@ -215,10 +248,20 @@ public: int &FrameIndex) const; /// Branch Analysis + virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl<MachineOperand> &Cond, + bool AllowModify) const; virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, const SmallVectorImpl<MachineOperand> &Cond, DebugLoc DL) const; + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const; + + virtual bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) + const; + + virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.td b/lib/Target/MBlaze/MBlazeInstrInfo.td index 7c6c9aa..7b8f70a 100644 --- a/lib/Target/MBlaze/MBlazeInstrInfo.td +++ b/lib/Target/MBlaze/MBlazeInstrInfo.td @@ -18,7 +18,8 @@ include "MBlazeInstrFormats.td" // def SDTMBlazeSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>]>; def SDT_MBlazeRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; -def SDT_MBlazeJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; +def SDT_MBlazeIRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; +def SDT_MBlazeJmpLink : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>; def SDT_MBCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; @@ -27,18 +28,21 @@ def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; //===----------------------------------------------------------------------===// def MBlazeRet : SDNode<"MBlazeISD::Ret", SDT_MBlazeRet, - [SDNPHasChain, SDNPOptInFlag]>; + [SDNPHasChain, SDNPOptInGlue]>; +def MBlazeIRet : SDNode<"MBlazeISD::IRet", SDT_MBlazeIRet, + [SDNPHasChain, SDNPOptInGlue]>; def MBlazeJmpLink : SDNode<"MBlazeISD::JmpLink",SDT_MBlazeJmpLink, - [SDNPHasChain,SDNPOptInFlag,SDNPOutFlag]>; + [SDNPHasChain,SDNPOptInGlue,SDNPOutGlue, + SDNPVariadic]>; def MBWrapper : SDNode<"MBlazeISD::Wrap", SDTIntUnaryOp>; def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MBCallSeqStart, - [SDNPHasChain, SDNPOutFlag]>; + [SDNPHasChain, SDNPOutGlue]>; def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MBCallSeqEnd, - [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; //===----------------------------------------------------------------------===// // MBlaze Instruction Predicate Definitions. @@ -79,7 +83,6 @@ def brtarget : Operand<OtherVT>; def calltarget : Operand<i32>; def simm16 : Operand<i32>; def uimm5 : Operand<i32>; -def uimm14 : Operand<i32>; def uimm15 : Operand<i32>; def fimm : Operand<f32>; @@ -169,6 +172,11 @@ class ArithI<bits<6> op, string instr_asm, SDNode OpNode, !strconcat(instr_asm, " $dst, $b, $c"), [(set GPR:$dst, (OpNode GPR:$b, imm_type:$c))], IIAlu>; +class ArithI32<bits<6> op, string instr_asm,Operand Od, PatLeaf imm_type> : + TB<op, (outs GPR:$dst), (ins GPR:$b, Od:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; + class ShiftI<bits<6> op, bits<2> flags, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : SHT<op, flags, (outs GPR:$dst), (ins GPR:$b, Od:$c), @@ -224,6 +232,11 @@ class LogicI<bits<6> op, string instr_asm, SDNode OpNode> : [(set GPR:$dst, (OpNode GPR:$b, immZExt16:$c))], IIAlu>; +class LogicI32<bits<6> op, string instr_asm> : + TB<op, (outs GPR:$dst), (ins GPR:$b, uimm16:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [], IIAlu>; + class PatCmp<bits<6> op, bits<11> flags, string instr_asm> : TA<op, flags, (outs GPR:$dst), (ins GPR:$b, GPR:$c), !strconcat(instr_asm, " $dst, $b, $c"), @@ -277,7 +290,7 @@ class BranchI<bits<6> op, bits<5> br, string instr_asm> : // Branch and Link Instructions //===----------------------------------------------------------------------===// class BranchL<bits<6> op, bits<5> br, bits<11> flags, string instr_asm> : - TA<op, flags, (outs), (ins GPR:$link, GPR:$target), + TA<op, flags, (outs), (ins GPR:$link, GPR:$target, variable_ops), !strconcat(instr_asm, " $link, $target"), [], IIBranch> { let ra = br; @@ -285,7 +298,7 @@ class BranchL<bits<6> op, bits<5> br, bits<11> flags, string instr_asm> : } class BranchLI<bits<6> op, bits<5> br, string instr_asm> : - TB<op, (outs), (ins GPR:$link, calltarget:$target), + TB<op, (outs), (ins GPR:$link, calltarget:$target, variable_ops), !strconcat(instr_asm, " $link, $target"), [], IIBranch> { let ra = br; @@ -317,26 +330,44 @@ class BranchCI<bits<6> op, bits<5> br, string instr_asm> : //===----------------------------------------------------------------------===// let isCommutable = 1, isAsCheapAsAMove = 1 in { - def ADD : Arith<0x00, 0x000, "add ", add, IIAlu>; - def ADDC : Arith<0x02, 0x000, "addc ", adde, IIAlu>; - def ADDK : Arith<0x04, 0x000, "addk ", addc, IIAlu>; - def ADDKC : ArithN<0x06, 0x000, "addkc ", IIAlu>; + def ADDK : Arith<0x04, 0x000, "addk ", add, IIAlu>; def AND : Logic<0x21, 0x000, "and ", and>; def OR : Logic<0x20, 0x000, "or ", or>; def XOR : Logic<0x22, 0x000, "xor ", xor>; def PCMPBF : PatCmp<0x20, 0x400, "pcmpbf ">; def PCMPEQ : PatCmp<0x22, 0x400, "pcmpeq ">; def PCMPNE : PatCmp<0x23, 0x400, "pcmpne ">; + + let Defs = [CARRY] in { + def ADD : Arith<0x00, 0x000, "add ", addc, IIAlu>; + + let Uses = [CARRY] in { + def ADDC : Arith<0x02, 0x000, "addc ", adde, IIAlu>; + } + } + + let Uses = [CARRY] in { + def ADDKC : ArithN<0x06, 0x000, "addkc ", IIAlu>; + } } let isAsCheapAsAMove = 1 in { def ANDN : ArithN<0x23, 0x000, "andn ", IIAlu>; def CMP : ArithN<0x05, 0x001, "cmp ", IIAlu>; def CMPU : ArithN<0x05, 0x003, "cmpu ", IIAlu>; - def RSUB : ArithR<0x01, 0x000, "rsub ", sub, IIAlu>; - def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIAlu>; - def RSUBK : ArithR<0x05, 0x000, "rsubk ", subc, IIAlu>; - def RSUBKC : ArithRN<0x07, 0x000, "rsubkc ", IIAlu>; + def RSUBK : ArithR<0x05, 0x000, "rsubk ", sub, IIAlu>; + + let Defs = [CARRY] in { + def RSUB : ArithR<0x01, 0x000, "rsub ", subc, IIAlu>; + + let Uses = [CARRY] in { + def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIAlu>; + } + } + + let Uses = [CARRY] in { + def RSUBKC : ArithRN<0x07, 0x000, "rsubkc ", IIAlu>; + } } let isCommutable = 1, Predicates=[HasMul] in { @@ -362,8 +393,8 @@ let Predicates=[HasBarrel] in { } let Predicates=[HasDiv] in { - def IDIV : Arith<0x12, 0x000, "idiv ", sdiv, IIAlu>; - def IDIVU : Arith<0x12, 0x002, "idivu ", udiv, IIAlu>; + def IDIV : ArithR<0x12, 0x000, "idiv ", sdiv, IIAlu>; + def IDIVU : ArithR<0x12, 0x002, "idivu ", udiv, IIAlu>; } //===----------------------------------------------------------------------===// @@ -371,18 +402,27 @@ let Predicates=[HasDiv] in { //===----------------------------------------------------------------------===// let isAsCheapAsAMove = 1 in { - def ADDI : ArithI<0x08, "addi ", add, simm16, immSExt16>; - def ADDIC : ArithNI<0x0A, "addic ", simm16, immSExt16>; - def ADDIK : ArithNI<0x0C, "addik ", simm16, immSExt16>; - def ADDIKC : ArithI<0x0E, "addikc ", addc, simm16, immSExt16>; - def RSUBI : ArithRI<0x09, "rsubi ", sub, simm16, immSExt16>; - def RSUBIC : ArithRNI<0x0B, "rsubic ", simm16, immSExt16>; - def RSUBIK : ArithRNI<0x0D, "rsubik ", simm16, immSExt16>; - def RSUBIKC : ArithRI<0x0F, "rsubikc", subc, simm16, immSExt16>; + def ADDIK : ArithI<0x0C, "addik ", add, simm16, immSExt16>; + def RSUBIK : ArithRI<0x0D, "rsubik ", sub, simm16, immSExt16>; def ANDNI : ArithNI<0x2B, "andni ", uimm16, immZExt16>; def ANDI : LogicI<0x29, "andi ", and>; def ORI : LogicI<0x28, "ori ", or>; def XORI : LogicI<0x2A, "xori ", xor>; + + let Defs = [CARRY] in { + def ADDI : ArithI<0x08, "addi ", addc, simm16, immSExt16>; + def RSUBI : ArithRI<0x09, "rsubi ", subc, simm16, immSExt16>; + + let Uses = [CARRY] in { + def ADDIC : ArithI<0x0A, "addic ", adde, simm16, immSExt16>; + def RSUBIC : ArithRI<0x0B, "rsubic ", sube, simm16, immSExt16>; + } + } + + let Uses = [CARRY] in { + def ADDIKC : ArithNI<0x0E, "addikc ", simm16, immSExt16>; + def RSUBIKC : ArithRNI<0x0F, "rsubikc", simm16, immSExt16>; + } } let Predicates=[HasMul] in { @@ -402,26 +442,32 @@ let canFoldAsLoad = 1, isReMaterializable = 1 in { def LW : LoadM<0x32, 0x000, "lw ">; def LWR : LoadM<0x32, 0x200, "lwr ">; - def LWX : LoadM<0x32, 0x400, "lwx ">; + + let Defs = [CARRY] in { + def LWX : LoadM<0x32, 0x400, "lwx ">; + } def LBUI : LoadMI<0x38, "lbui ", zextloadi8>; def LHUI : LoadMI<0x39, "lhui ", zextloadi16>; def LWI : LoadMI<0x3A, "lwi ", load>; } - def SB : StoreM<0x34, 0x000, "sb ">; - def SBR : StoreM<0x34, 0x200, "sbr ">; +def SB : StoreM<0x34, 0x000, "sb ">; +def SBR : StoreM<0x34, 0x200, "sbr ">; - def SH : StoreM<0x35, 0x000, "sh ">; - def SHR : StoreM<0x35, 0x200, "shr ">; +def SH : StoreM<0x35, 0x000, "sh ">; +def SHR : StoreM<0x35, 0x200, "shr ">; - def SW : StoreM<0x36, 0x000, "sw ">; - def SWR : StoreM<0x36, 0x200, "swr ">; +def SW : StoreM<0x36, 0x000, "sw ">; +def SWR : StoreM<0x36, 0x200, "swr ">; + +let Defs = [CARRY] in { def SWX : StoreM<0x36, 0x400, "swx ">; +} - def SBI : StoreMI<0x3C, "sbi ", truncstorei8>; - def SHI : StoreMI<0x3D, "shi ", truncstorei16>; - def SWI : StoreMI<0x3E, "swi ", store>; +def SBI : StoreMI<0x3C, "sbi ", truncstorei8>; +def SHI : StoreMI<0x3D, "shi ", truncstorei16>; +def SWI : StoreMI<0x3E, "swi ", store>; //===----------------------------------------------------------------------===// // MBlaze branch instructions @@ -487,23 +533,22 @@ let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, def BGED : BranchC<0x27, 0x15, 0x000, "bged ">; } -let isCall = 1, hasDelaySlot = 1, hasCtrlDep = 1, isBarrier = 1, - Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12], - Uses = [R1,R5,R6,R7,R8,R9,R10] in { +let isCall =1, hasDelaySlot = 1, + Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,CARRY], + Uses = [R1] in { def BRLID : BranchLI<0x2E, 0x14, "brlid ">; def BRALID : BranchLI<0x2E, 0x1C, "bralid ">; } -let isCall = 1, hasDelaySlot = 1, hasCtrlDep = 1, isIndirectBranch = 1, - isBarrier = 1, - Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12], - Uses = [R1,R5,R6,R7,R8,R9,R10] in { +let isCall = 1, hasDelaySlot = 1, + Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,CARRY], + Uses = [R1] in { def BRLD : BranchL<0x26, 0x14, 0x000, "brld ">; def BRALD : BranchL<0x26, 0x1C, 0x000, "brald ">; } let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, - hasCtrlDep=1, rd=0x10, Form=FCRI in { + rd=0x10, Form=FCRI in { def RTSD : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rtsd $target, $imm", [], @@ -511,7 +556,7 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, } let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, - hasCtrlDep=1, rd=0x11, Form=FCRI in { + rd=0x11, Form=FCRI in { def RTID : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rtid $target, $imm", [], @@ -519,7 +564,7 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, } let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, - hasCtrlDep=1, rd=0x12, Form=FCRI in { + rd=0x12, Form=FCRI in { def RTBD : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rtbd $target, $imm", [], @@ -527,7 +572,7 @@ let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, } let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, - hasCtrlDep=1, rd=0x14, Form=FCRI in { + rd=0x14, Form=FCRI in { def RTED : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rted $target, $imm", [], @@ -544,7 +589,7 @@ let neverHasSideEffects = 1 in { let usesCustomInserter = 1 in { def Select_CC : MBlazePseudo<(outs GPR:$dst), - (ins GPR:$T, GPR:$F, GPR:$CMP, i32imm:$CC), + (ins GPR:$T, GPR:$F, GPR:$CMP, i32imm:$CC), // F T reversed "; SELECT_CC PSEUDO!", []>; @@ -564,34 +609,41 @@ let usesCustomInserter = 1 in { []>; } - let rb = 0 in { def SEXT16 : TA<0x24, 0x061, (outs GPR:$dst), (ins GPR:$src), "sext16 $dst, $src", [], IIAlu>; def SEXT8 : TA<0x24, 0x060, (outs GPR:$dst), (ins GPR:$src), "sext8 $dst, $src", [], IIAlu>; - def SRL : TA<0x24, 0x041, (outs GPR:$dst), (ins GPR:$src), - "srl $dst, $src", [], IIAlu>; - def SRA : TA<0x24, 0x001, (outs GPR:$dst), (ins GPR:$src), - "sra $dst, $src", [], IIAlu>; - def SRC : TA<0x24, 0x021, (outs GPR:$dst), (ins GPR:$src), - "src $dst, $src", [], IIAlu>; + let Defs = [CARRY] in { + def SRL : TA<0x24, 0x041, (outs GPR:$dst), (ins GPR:$src), + "srl $dst, $src", [], IIAlu>; + def SRA : TA<0x24, 0x001, (outs GPR:$dst), (ins GPR:$src), + "sra $dst, $src", [], IIAlu>; + let Uses = [CARRY] in { + def SRC : TA<0x24, 0x021, (outs GPR:$dst), (ins GPR:$src), + "src $dst, $src", [], IIAlu>; + } + } } -let opcode=0x08, isCodeGenOnly=1 in { - def LEA_ADDI : TB<0x08, (outs GPR:$dst), (ins memri:$addr), - "addi $dst, ${addr:stackloc}", - [(set GPR:$dst, iaddr:$addr)], IIAlu>; +let isCodeGenOnly=1 in { + def ADDIK32 : ArithI32<0x08, "addik ", simm16, immSExt16>; + def ORI32 : LogicI32<0x28, "ori ">; + def BRLID32 : BranchLI<0x2E, 0x14, "brlid ">; } //===----------------------------------------------------------------------===// // Misc. instructions //===----------------------------------------------------------------------===// -def MFS : SPC<0x25, 0x2, (outs GPR:$dst), (ins uimm14:$rg), - "mfs $dst, $rg", [], IIAlu>; +let Form=FRCS in { + def MFS : SPC<0x25, 0x2, (outs GPR:$dst), (ins SPR:$src), + "mfs $dst, $src", [], IIAlu>; +} -def MTS : SPC<0x25, 0x3, (outs), (ins uimm14:$dst, GPR:$rg), - "mts $dst, $rg", [], IIAlu>; +let Form=FCRCS in { + def MTS : SPC<0x25, 0x3, (outs SPR:$dst), (ins GPR:$src), + "mts $dst, $src", [], IIAlu>; +} def MSRSET : MSR<0x25, 0x20, (outs GPR:$dst), (ins uimm15:$set), "msrset $dst, $set", [], IIAlu>; @@ -617,16 +669,57 @@ def IMM : MBlazeInst<0x2C, FCCI, (outs), (ins simm16:$imm), "imm $imm", [], IIAlu>; //===----------------------------------------------------------------------===// +// Pseudo instructions for atomic operations +//===----------------------------------------------------------------------===// +let usesCustomInserter=1 in { + def CAS32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$cmp, GPR:$swp), + "# atomic compare and swap", + [(set GPR:$dst, (atomic_cmp_swap_32 GPR:$ptr, GPR:$cmp, GPR:$swp))]>; + + def SWP32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$swp), + "# atomic swap", + [(set GPR:$dst, (atomic_swap_32 GPR:$ptr, GPR:$swp))]>; + + def LAA32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and add", + [(set GPR:$dst, (atomic_load_add_32 GPR:$ptr, GPR:$val))]>; + + def LAS32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and sub", + [(set GPR:$dst, (atomic_load_sub_32 GPR:$ptr, GPR:$val))]>; + + def LAD32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and and", + [(set GPR:$dst, (atomic_load_and_32 GPR:$ptr, GPR:$val))]>; + + def LAO32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and or", + [(set GPR:$dst, (atomic_load_or_32 GPR:$ptr, GPR:$val))]>; + + def LAX32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and xor", + [(set GPR:$dst, (atomic_load_xor_32 GPR:$ptr, GPR:$val))]>; + + def LAN32 : MBlazePseudo<(outs GPR:$dst), (ins GPR:$ptr, GPR:$val), + "# atomic load and nand", + [(set GPR:$dst, (atomic_load_nand_32 GPR:$ptr, GPR:$val))]>; + + def MEMBARRIER : MBlazePseudo<(outs), (ins), + "# memory barrier", + [(membarrier (i32 imm), (i32 imm), (i32 imm), (i32 imm), (i32 imm))]>; +} + +//===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// // Small immediates -def : Pat<(i32 0), (ADD (i32 R0), (i32 R0))>; -def : Pat<(i32 immSExt16:$imm), (ADDI (i32 R0), imm:$imm)>; +def : Pat<(i32 0), (ADDK (i32 R0), (i32 R0))>; +def : Pat<(i32 immSExt16:$imm), (ADDIK (i32 R0), imm:$imm)>; def : Pat<(i32 immZExt16:$imm), (ORI (i32 R0), imm:$imm)>; // Arbitrary immediates -def : Pat<(i32 imm:$imm), (ADDI (i32 R0), imm:$imm)>; +def : Pat<(i32 imm:$imm), (ADDIK (i32 R0), imm:$imm)>; // In register sign extension def : Pat<(sext_inreg GPR:$src, i16), (SEXT16 GPR:$src)>; @@ -640,7 +733,7 @@ def : Pat<(MBlazeJmpLink (i32 texternalsym:$dst)), (BRLID (i32 R15), texternalsym:$dst)>; def : Pat<(MBlazeJmpLink GPR:$dst), - (BRLD (i32 R15), GPR:$dst)>; + (BRALD (i32 R15), GPR:$dst)>; // Shift Instructions def : Pat<(shl GPR:$L, GPR:$R), (ShiftL GPR:$L, GPR:$R)>; @@ -649,35 +742,35 @@ def : Pat<(srl GPR:$L, GPR:$R), (ShiftRL GPR:$L, GPR:$R)>; // SET_CC operations def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETEQ), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), - (CMP GPR:$L, GPR:$R), 1)>; + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 1)>; def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETNE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), - (CMP GPR:$L, GPR:$R), 2)>; + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 2)>; def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETGT), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), - (CMP GPR:$L, GPR:$R), 3)>; + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 3)>; def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETLT), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), - (CMP GPR:$L, GPR:$R), 4)>; + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 4)>; def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETGE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), - (CMP GPR:$L, GPR:$R), 5)>; + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 5)>; def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETLE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), - (CMP GPR:$L, GPR:$R), 6)>; + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMP GPR:$R, GPR:$L), 6)>; def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETUGT), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), - (CMPU GPR:$L, GPR:$R), 3)>; + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMPU GPR:$R, GPR:$L), 3)>; def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETULT), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), - (CMPU GPR:$L, GPR:$R), 4)>; + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMPU GPR:$R, GPR:$L), 4)>; def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETUGE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), - (CMPU GPR:$L, GPR:$R), 5)>; + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMPU GPR:$R, GPR:$L), 5)>; def : Pat<(setcc (i32 GPR:$L), (i32 GPR:$R), SETULE), - (Select_CC (ADDI (i32 R0), 1), (ADDI (i32 R0), 0), - (CMPU GPR:$L, GPR:$R), 6)>; + (Select_CC (ADDIK (i32 R0), 1), (ADDIK (i32 R0), 0), + (CMPU GPR:$R, GPR:$L), 6)>; // SELECT operations def : Pat<(select (i32 GPR:$C), (i32 GPR:$T), (i32 GPR:$F)), @@ -686,41 +779,42 @@ def : Pat<(select (i32 GPR:$C), (i32 GPR:$T), (i32 GPR:$F)), // SELECT_CC def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), (i32 GPR:$T), (i32 GPR:$F), SETEQ), - (Select_CC GPR:$T, GPR:$F, (CMP GPR:$L, GPR:$R), 1)>; + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 1)>; def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), (i32 GPR:$T), (i32 GPR:$F), SETNE), - (Select_CC GPR:$T, GPR:$F, (CMP GPR:$L, GPR:$R), 2)>; + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 2)>; def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), (i32 GPR:$T), (i32 GPR:$F), SETGT), - (Select_CC GPR:$T, GPR:$F, (CMP GPR:$L, GPR:$R), 3)>; + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 3)>; def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), (i32 GPR:$T), (i32 GPR:$F), SETLT), - (Select_CC GPR:$T, GPR:$F, (CMP GPR:$L, GPR:$R), 4)>; + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 4)>; def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), (i32 GPR:$T), (i32 GPR:$F), SETGE), - (Select_CC GPR:$T, GPR:$F, (CMP GPR:$L, GPR:$R), 5)>; + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 5)>; def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), (i32 GPR:$T), (i32 GPR:$F), SETLE), - (Select_CC GPR:$T, GPR:$F, (CMP GPR:$L, GPR:$R), 6)>; + (Select_CC GPR:$T, GPR:$F, (CMP GPR:$R, GPR:$L), 6)>; def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), (i32 GPR:$T), (i32 GPR:$F), SETUGT), - (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$L, GPR:$R), 3)>; + (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$R, GPR:$L), 3)>; def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), (i32 GPR:$T), (i32 GPR:$F), SETULT), - (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$L, GPR:$R), 4)>; + (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$R, GPR:$L), 4)>; def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), (i32 GPR:$T), (i32 GPR:$F), SETUGE), - (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$L, GPR:$R), 5)>; + (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$R, GPR:$L), 5)>; def : Pat<(selectcc (i32 GPR:$L), (i32 GPR:$R), (i32 GPR:$T), (i32 GPR:$F), SETULE), - (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$L, GPR:$R), 6)>; + (Select_CC GPR:$T, GPR:$F, (CMPU GPR:$R, GPR:$L), 6)>; // Ret instructions def : Pat<(MBlazeRet GPR:$target), (RTSD GPR:$target, 0x8)>; +def : Pat<(MBlazeIRet GPR:$target), (RTID GPR:$target, 0x0)>; // BR instructions def : Pat<(br bb:$T), (BRID bb:$T)>; -def : Pat<(brind GPR:$T), (BRD GPR:$T)>; +def : Pat<(brind GPR:$T), (BRAD GPR:$T)>; // BRCOND instructions def : Pat<(brcond (setcc (i32 GPR:$L), (i32 GPR:$R), SETEQ), bb:$T), @@ -755,7 +849,7 @@ def : Pat<(MBWrapper tconstpool:$in), (ORI (i32 R0), tconstpool:$in)>; def : Pat<(and (i32 GPR:$lh), (not (i32 GPR:$rh))),(ANDN GPR:$lh, GPR:$rh)>; // Arithmetic with immediates -def : Pat<(add (i32 GPR:$in), imm:$imm),(ADDI GPR:$in, imm:$imm)>; +def : Pat<(add (i32 GPR:$in), imm:$imm),(ADDIK GPR:$in, imm:$imm)>; def : Pat<(or (i32 GPR:$in), imm:$imm),(ORI GPR:$in, imm:$imm)>; def : Pat<(xor (i32 GPR:$in), imm:$imm),(XORI GPR:$in, imm:$imm)>; diff --git a/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp b/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp index 23b8246..1467141 100644 --- a/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp +++ b/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp @@ -15,13 +15,8 @@ using namespace llvm; MBlazeMCAsmInfo::MBlazeMCAsmInfo() { + SupportsDebugInformation = true; AlignmentIsInBytes = false; - Data16bitsDirective = "\t.half\t"; - Data32bitsDirective = "\t.word\t"; - Data64bitsDirective = 0; PrivateGlobalPrefix = "$"; - CommentString = "#"; - ZeroDirective = "\t.space\t"; GPRel32Directive = "\t.gpword\t"; - HasSetDirective = false; } diff --git a/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp b/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp index 19dc89b..3ece1a8 100644 --- a/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp +++ b/lib/Target/MBlaze/MBlazeMCCodeEmitter.cpp @@ -14,7 +14,6 @@ #define DEBUG_TYPE "mccodeemitter" #include "MBlaze.h" #include "MBlazeInstrInfo.h" -#include "MBlazeFixupKinds.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" @@ -52,25 +51,6 @@ public: return getMachineOpValue(MI, MI.getOperand(OpIdx)); } - unsigned getNumFixupKinds() const { - return 2; - } - - const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { - const static MCFixupKindInfo Infos[] = { - { "reloc_pcrel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel }, - { "reloc_pcrel_2byte", 0, 2 * 8, MCFixupKindInfo::FKF_IsPCRel } }; - - if (Kind < FirstTargetFixupKind) - return MCCodeEmitter::getFixupKindInfo(Kind); - - if (unsigned(Kind-FirstTargetFixupKind) < getNumFixupKinds()) - return Infos[Kind - FirstTargetFixupKind]; - - assert(0 && "Invalid fixup kind."); - return Infos[0]; - } - static unsigned GetMBlazeRegNum(const MCOperand &MO) { // FIXME: getMBlazeRegisterNumbering() is sufficient? assert(0 && "MBlazeMCCodeEmitter::GetMBlazeRegNum() not yet implemented."); @@ -103,11 +83,9 @@ public: } void EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const; - void EmitIMM(const MCInst &MI, unsigned op, unsigned &CurByte, - raw_ostream &OS) const; + void EmitIMM(const MCInst &MI, unsigned &CurByte, raw_ostream &OS) const; - void EmitImmediate(const MCInst &MI, - unsigned opNo, MCFixupKind FixupKind, + void EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel, unsigned &CurByte, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const; @@ -155,28 +133,43 @@ EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const { } void MBlazeMCCodeEmitter:: -EmitIMM(const MCInst &MI, unsigned op, unsigned &CurByte, - raw_ostream &OS) const { - MCOperand mcop = MI.getOperand(op); - if (mcop.isExpr()) { - EmitByte(0x0D, CurByte, OS); - EmitByte(0x00, CurByte, OS); - EmitRawByte(0, CurByte, OS); - EmitRawByte(0, CurByte, OS); - } +EmitIMM(const MCInst &MI, unsigned &CurByte,raw_ostream &OS) const { + switch (MI.getOpcode()) { + default: break; + + case MBlaze::ADDIK32: + case MBlaze::ORI32: + case MBlaze::BRLID32: + EmitByte(0x0D, CurByte, OS); + EmitByte(0x00, CurByte, OS); + EmitRawByte(0, CurByte, OS); + EmitRawByte(0, CurByte, OS); + } } void MBlazeMCCodeEmitter:: -EmitImmediate(const MCInst &MI, unsigned opNo, MCFixupKind FixupKind, - unsigned &CurByte, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups) const { +EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel, unsigned &CurByte, + raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const { assert(MI.getNumOperands()>opNo && "Not enought operands for instruction"); MCOperand oper = MI.getOperand(opNo); + if (oper.isImm()) { - EmitIMM(oper, CurByte, OS); + EmitIMM(oper, CurByte, OS); } else if (oper.isExpr()) { + MCFixupKind FixupKind; + switch (MI.getOpcode()) { + default: + FixupKind = pcrel ? FK_PCRel_2 : FK_Data_2; Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind)); + break; + case MBlaze::ORI32: + case MBlaze::ADDIK32: + case MBlaze::BRLID32: + FixupKind = pcrel ? FK_PCRel_4 : FK_Data_4; + Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind)); + break; + } } } @@ -191,56 +184,33 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, // Keep track of the current byte being emitted. unsigned CurByte = 0; + // Emit an IMM instruction if the instruction we are encoding requires it + EmitIMM(MI,CurByte,OS); + switch ((TSFlags & MBlazeII::FormMask)) { default: break; case MBlazeII::FPseudo: // Pseudo instructions don't get encoded. return; - case MBlazeII::FRRI: - EmitImmediate(MI, 2, FK_Data_4, CurByte, OS, Fixups); + EmitImmediate(MI, 2, false, CurByte, OS, Fixups); break; - case MBlazeII::FRIR: - EmitImmediate(MI, 1, FK_Data_4, CurByte, OS, Fixups); + EmitImmediate(MI, 1, false, CurByte, OS, Fixups); break; - case MBlazeII::FCRI: - EmitImmediate(MI, 1, MCFixupKind(MBlaze::reloc_pcrel_2byte), CurByte, OS, - Fixups); + EmitImmediate(MI, 1, true, CurByte, OS, Fixups); break; - case MBlazeII::FRCI: - EmitImmediate(MI, 1, MCFixupKind(MBlaze::reloc_pcrel_4byte), CurByte, OS, - Fixups); - + EmitImmediate(MI, 1, true, CurByte, OS, Fixups); case MBlazeII::FCCI: - EmitImmediate(MI, 0, MCFixupKind(MBlaze::reloc_pcrel_4byte), CurByte, OS, - Fixups); + EmitImmediate(MI, 0, true, CurByte, OS, Fixups); break; } ++MCNumEmitted; // Keep track of the # of mi's emitted unsigned Value = getBinaryCodeForInstr(MI); - switch (Opcode) { - default: - EmitConstant(Value, 4, CurByte, OS); - break; - - case MBlaze::BRLID: - case MBlaze::BRALID: - EmitIMM(MI,1,CurByte,OS); - EmitConstant(Value, 4, CurByte, OS); - break; - - case MBlaze::BRI: - case MBlaze::BRAI: - case MBlaze::BRID: - case MBlaze::BRAID: - EmitIMM(MI,0,CurByte,OS); - EmitConstant(Value, 4, CurByte, OS); - break; - } + EmitConstant(Value, 4, CurByte, OS); } // FIXME: These #defines shouldn't be necessary. Instead, tblgen should diff --git a/lib/Target/MBlaze/MBlazeMCInstLower.cpp b/lib/Target/MBlaze/MBlazeMCInstLower.cpp index 2a48c0d..a7e400b 100644 --- a/lib/Target/MBlaze/MBlazeMCInstLower.cpp +++ b/lib/Target/MBlaze/MBlazeMCInstLower.cpp @@ -32,10 +32,8 @@ using namespace llvm; MCSymbol *MBlazeMCInstLower:: GetGlobalAddressSymbol(const MachineOperand &MO) const { switch (MO.getTargetFlags()) { - default: - llvm_unreachable("Unknown target flag on GV operand"); - - case 0: break; + default: llvm_unreachable("Unknown target flag on GV operand"); + case 0: break; } return Printer.Mang->getSymbol(MO.getGlobal()); @@ -44,10 +42,8 @@ GetGlobalAddressSymbol(const MachineOperand &MO) const { MCSymbol *MBlazeMCInstLower:: GetExternalSymbolSymbol(const MachineOperand &MO) const { switch (MO.getTargetFlags()) { - default: - assert(0 && "Unknown target flag on GV operand"); - - case 0: break; + default: llvm_unreachable("Unknown target flag on GV operand"); + case 0: break; } return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); @@ -59,12 +55,9 @@ GetJumpTableSymbol(const MachineOperand &MO) const { raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI" << Printer.getFunctionNumber() << '_' << MO.getIndex(); - switch (MO.getTargetFlags()) { - default: - llvm_unreachable("Unknown target flag on GV operand"); - - case 0: break; + default: llvm_unreachable("Unknown target flag on GV operand"); + case 0: break; } // Create a symbol for the name. @@ -129,8 +122,7 @@ void MBlazeMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { MCOperand MCOp; switch (MO.getType()) { - default: - assert(0 && "unknown operand type"); + default: llvm_unreachable("unknown operand type"); case MachineOperand::MO_Register: // Ignore all implicit register operands. if (MO.isImplicit()) continue; diff --git a/lib/Target/MBlaze/MBlazeMachineFunction.h b/lib/Target/MBlaze/MBlazeMachineFunction.h index da74712..df39509 100644 --- a/lib/Target/MBlaze/MBlazeMachineFunction.h +++ b/lib/Target/MBlaze/MBlazeMachineFunction.h @@ -14,6 +14,7 @@ #ifndef MBLAZE_MACHINE_FUNCTION_INFO_H #define MBLAZE_MACHINE_FUNCTION_INFO_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/VectorExtras.h" #include "llvm/CodeGen/MachineFunction.h" @@ -34,12 +35,6 @@ private: /// saved. This is used on Prologue and Epilogue to emit RA save/restore int RAStackOffset; - /// At each function entry a special bitmask directive must be emitted - /// to help in debugging CPU callee saved registers. It needs a negative - /// offset from the final stack size and its higher register location on - /// the stack. - int CPUTopSavedRegOff; - /// MBlazeFIHolder - Holds a FrameIndex and it's Stack Pointer Offset struct MBlazeFIHolder { @@ -69,6 +64,11 @@ private: SmallVector<MBlazeFIHolder, 4> FnStoreVarArgs; bool HasStoreVarArgs; + // When determining the final stack layout some of the frame indexes may + // be replaced by new frame indexes that reside in the caller's stack + // frame. The replacements are recorded in this structure. + DenseMap<int,int> FIReplacements; + /// SRetReturnReg - Some subtargets require that sret lowering includes /// returning the value of the returned struct in a register. This field /// holds the virtual register into which the sret argument is passed. @@ -82,11 +82,15 @@ private: // VarArgsFrameIndex - FrameIndex for start of varargs area. int VarArgsFrameIndex; + /// LiveInFI - keeps track of the frame indexes in a callers stack + /// frame that are live into a function. + SmallVector<int, 16> LiveInFI; + public: MBlazeFunctionInfo(MachineFunction& MF) - : FPStackOffset(0), RAStackOffset(0), CPUTopSavedRegOff(0), - GPHolder(-1,-1), HasLoadArgs(false), HasStoreVarArgs(false), - SRetReturnReg(0), GlobalBaseReg(0), VarArgsFrameIndex(0) + : FPStackOffset(0), RAStackOffset(0), GPHolder(-1,-1), HasLoadArgs(false), + HasStoreVarArgs(false), SRetReturnReg(0), GlobalBaseReg(0), + VarArgsFrameIndex(0), LiveInFI() {} int getFPStackOffset() const { return FPStackOffset; } @@ -95,9 +99,6 @@ public: int getRAStackOffset() const { return RAStackOffset; } void setRAStackOffset(int Off) { RAStackOffset = Off; } - int getCPUTopSavedRegOff() const { return CPUTopSavedRegOff; } - void setCPUTopSavedRegOff(int Off) { CPUTopSavedRegOff = Off; } - int getGPStackOffset() const { return GPHolder.SPOffset; } int getGPFI() const { return GPHolder.FI; } void setGPStackOffset(int Off) { GPHolder.SPOffset = Off; } @@ -107,10 +108,36 @@ public: bool hasLoadArgs() const { return HasLoadArgs; } bool hasStoreVarArgs() const { return HasStoreVarArgs; } + void recordLiveIn(int FI) { + LiveInFI.push_back(FI); + } + + bool isLiveIn(int FI) { + for (unsigned i = 0, e = LiveInFI.size(); i < e; ++i) + if (FI == LiveInFI[i]) return true; + + return false; + } + + const SmallVector<int, 16>& getLiveIn() const { return LiveInFI; } + + void recordReplacement(int OFI, int NFI) { + FIReplacements.insert(std::make_pair(OFI,NFI)); + } + + bool hasReplacement(int OFI) const { + return FIReplacements.find(OFI) != FIReplacements.end(); + } + + int getReplacement(int OFI) const { + return FIReplacements.lookup(OFI); + } + void recordLoadArgsFI(int FI, int SPOffset) { if (!HasLoadArgs) HasLoadArgs=true; FnLoadArgs.push_back(MBlazeFIHolder(FI, SPOffset)); } + void recordStoreVarArgsFI(int FI, int SPOffset) { if (!HasStoreVarArgs) HasStoreVarArgs=true; FnStoreVarArgs.push_back(MBlazeFIHolder(FI, SPOffset)); @@ -121,6 +148,7 @@ public: for (unsigned i = 0, e = FnLoadArgs.size(); i != e; ++i) MFI->setObjectOffset(FnLoadArgs[i].FI, FnLoadArgs[i].SPOffset); } + void adjustStoreVarArgsFI(MachineFrameInfo *MFI) const { if (!hasStoreVarArgs()) return; for (unsigned i = 0, e = FnStoreVarArgs.size(); i != e; ++i) diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp index 37a30c7..fa9140d 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp @@ -1,5 +1,5 @@ //===- MBlazeRegisterInfo.cpp - MBlaze Register Information -== -*- C++ -*-===// -//DJ +// // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source @@ -12,7 +12,7 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "mblaze-reg-info" +#define DEBUG_TYPE "mblaze-frame-info" #include "MBlaze.h" #include "MBlazeSubtarget.h" @@ -26,7 +26,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineLocation.h" -#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetInstrInfo.h" @@ -48,38 +48,62 @@ MBlazeRegisterInfo(const MBlazeSubtarget &ST, const TargetInstrInfo &tii) /// MBlaze::R0, return the number that it corresponds to (e.g. 0). unsigned MBlazeRegisterInfo::getRegisterNumbering(unsigned RegEnum) { switch (RegEnum) { - case MBlaze::R0 : return 0; - case MBlaze::R1 : return 1; - case MBlaze::R2 : return 2; - case MBlaze::R3 : return 3; - case MBlaze::R4 : return 4; - case MBlaze::R5 : return 5; - case MBlaze::R6 : return 6; - case MBlaze::R7 : return 7; - case MBlaze::R8 : return 8; - case MBlaze::R9 : return 9; - case MBlaze::R10 : return 10; - case MBlaze::R11 : return 11; - case MBlaze::R12 : return 12; - case MBlaze::R13 : return 13; - case MBlaze::R14 : return 14; - case MBlaze::R15 : return 15; - case MBlaze::R16 : return 16; - case MBlaze::R17 : return 17; - case MBlaze::R18 : return 18; - case MBlaze::R19 : return 19; - case MBlaze::R20 : return 20; - case MBlaze::R21 : return 21; - case MBlaze::R22 : return 22; - case MBlaze::R23 : return 23; - case MBlaze::R24 : return 24; - case MBlaze::R25 : return 25; - case MBlaze::R26 : return 26; - case MBlaze::R27 : return 27; - case MBlaze::R28 : return 28; - case MBlaze::R29 : return 29; - case MBlaze::R30 : return 30; - case MBlaze::R31 : return 31; + case MBlaze::R0 : return 0; + case MBlaze::R1 : return 1; + case MBlaze::R2 : return 2; + case MBlaze::R3 : return 3; + case MBlaze::R4 : return 4; + case MBlaze::R5 : return 5; + case MBlaze::R6 : return 6; + case MBlaze::R7 : return 7; + case MBlaze::R8 : return 8; + case MBlaze::R9 : return 9; + case MBlaze::R10 : return 10; + case MBlaze::R11 : return 11; + case MBlaze::R12 : return 12; + case MBlaze::R13 : return 13; + case MBlaze::R14 : return 14; + case MBlaze::R15 : return 15; + case MBlaze::R16 : return 16; + case MBlaze::R17 : return 17; + case MBlaze::R18 : return 18; + case MBlaze::R19 : return 19; + case MBlaze::R20 : return 20; + case MBlaze::R21 : return 21; + case MBlaze::R22 : return 22; + case MBlaze::R23 : return 23; + case MBlaze::R24 : return 24; + case MBlaze::R25 : return 25; + case MBlaze::R26 : return 26; + case MBlaze::R27 : return 27; + case MBlaze::R28 : return 28; + case MBlaze::R29 : return 29; + case MBlaze::R30 : return 30; + case MBlaze::R31 : return 31; + case MBlaze::RPC : return 0x0000; + case MBlaze::RMSR : return 0x0001; + case MBlaze::REAR : return 0x0003; + case MBlaze::RESR : return 0x0005; + case MBlaze::RFSR : return 0x0007; + case MBlaze::RBTR : return 0x000B; + case MBlaze::REDR : return 0x000D; + case MBlaze::RPID : return 0x1000; + case MBlaze::RZPR : return 0x1001; + case MBlaze::RTLBX : return 0x1002; + case MBlaze::RTLBLO : return 0x1003; + case MBlaze::RTLBHI : return 0x1004; + case MBlaze::RPVR0 : return 0x2000; + case MBlaze::RPVR1 : return 0x2001; + case MBlaze::RPVR2 : return 0x2002; + case MBlaze::RPVR3 : return 0x2003; + case MBlaze::RPVR4 : return 0x2004; + case MBlaze::RPVR5 : return 0x2005; + case MBlaze::RPVR6 : return 0x2006; + case MBlaze::RPVR7 : return 0x2007; + case MBlaze::RPVR8 : return 0x2008; + case MBlaze::RPVR9 : return 0x2009; + case MBlaze::RPVR10 : return 0x200A; + case MBlaze::RPVR11 : return 0x200B; default: llvm_unreachable("Unknown register number!"); } return 0; // Not reached @@ -126,6 +150,37 @@ unsigned MBlazeRegisterInfo::getRegisterFromNumbering(unsigned Reg) { return 0; // Not reached } +unsigned MBlazeRegisterInfo::getSpecialRegisterFromNumbering(unsigned Reg) { + switch (Reg) { + case 0x0000 : return MBlaze::RPC; + case 0x0001 : return MBlaze::RMSR; + case 0x0003 : return MBlaze::REAR; + case 0x0005 : return MBlaze::RESR; + case 0x0007 : return MBlaze::RFSR; + case 0x000B : return MBlaze::RBTR; + case 0x000D : return MBlaze::REDR; + case 0x1000 : return MBlaze::RPID; + case 0x1001 : return MBlaze::RZPR; + case 0x1002 : return MBlaze::RTLBX; + case 0x1003 : return MBlaze::RTLBLO; + case 0x1004 : return MBlaze::RTLBHI; + case 0x2000 : return MBlaze::RPVR0; + case 0x2001 : return MBlaze::RPVR1; + case 0x2002 : return MBlaze::RPVR2; + case 0x2003 : return MBlaze::RPVR3; + case 0x2004 : return MBlaze::RPVR4; + case 0x2005 : return MBlaze::RPVR5; + case 0x2006 : return MBlaze::RPVR6; + case 0x2007 : return MBlaze::RPVR7; + case 0x2008 : return MBlaze::RPVR8; + case 0x2009 : return MBlaze::RPVR9; + case 0x200A : return MBlaze::RPVR10; + case 0x200B : return MBlaze::RPVR11; + default: llvm_unreachable("Unknown register number!"); + } + return 0; // Not reached +} + unsigned MBlazeRegisterInfo::getPICCallReg() { return MBlaze::R20; } @@ -164,19 +219,40 @@ getReservedRegs(const MachineFunction &MF) const { return Reserved; } -// hasFP - Return true if the specified function should have a dedicated frame -// pointer register. This is true if the function has variable sized allocas or -// if frame pointer elimination is disabled. -bool MBlazeRegisterInfo::hasFP(const MachineFunction &MF) const { - const MachineFrameInfo *MFI = MF.getFrameInfo(); - return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects(); -} - -// This function eliminate ADJCALLSTACKDOWN, -// ADJCALLSTACKUP pseudo instructions +// This function eliminate ADJCALLSTACKDOWN/ADJCALLSTACKUP pseudo instructions void MBlazeRegisterInfo:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + if (!TFI->hasReservedCallFrame(MF)) { + // If we have a frame pointer, turn the adjcallstackup instruction into a + // 'addi r1, r1, -<amt>' and the adjcallstackdown instruction into + // 'addi r1, r1, <amt>' + MachineInstr *Old = I; + int Amount = Old->getOperand(0).getImm() + 4; + if (Amount != 0) { + // We need to keep the stack aligned properly. To do this, we round the + // amount of space needed for the outgoing arguments up to the next + // alignment boundary. + unsigned Align = TFI->getStackAlignment(); + Amount = (Amount+Align-1)/Align*Align; + + MachineInstr *New; + if (Old->getOpcode() == MBlaze::ADJCALLSTACKDOWN) { + New = BuildMI(MF,Old->getDebugLoc(),TII.get(MBlaze::ADDIK),MBlaze::R1) + .addReg(MBlaze::R1).addImm(-Amount); + } else { + assert(Old->getOpcode() == MBlaze::ADJCALLSTACKUP); + New = BuildMI(MF,Old->getDebugLoc(),TII.get(MBlaze::ADDIK),MBlaze::R1) + .addReg(MBlaze::R1).addImm(Amount); + } + + // Replace the pseudo instruction with a new instruction... + MBB.insert(I, New); + } + } + // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. MBB.erase(I); } @@ -189,6 +265,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, RegScavenger *RS) const { MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); + MachineFrameInfo *MFI = MF.getFrameInfo(); unsigned i = 0; while (!MI.getOperand(i).isFI()) { @@ -199,23 +276,28 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned oi = i == 2 ? 1 : 2; - DEBUG(errs() << "\nFunction : " << MF.getFunction()->getName() << "\n"; - errs() << "<--------->\n" << MI); + DEBUG(dbgs() << "\nFunction : " << MF.getFunction()->getName() << "\n"; + dbgs() << "<--------->\n" << MI); int FrameIndex = MI.getOperand(i).getIndex(); - int stackSize = MF.getFrameInfo()->getStackSize(); - int spOffset = MF.getFrameInfo()->getObjectOffset(FrameIndex); + int stackSize = MFI->getStackSize(); + int spOffset = MFI->getObjectOffset(FrameIndex); - DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n" + DEBUG(MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); + dbgs() << "FrameIndex : " << FrameIndex << "\n" << "spOffset : " << spOffset << "\n" - << "stackSize : " << stackSize << "\n"); + << "stackSize : " << stackSize << "\n" + << "isFixed : " << MFI->isFixedObjectIndex(FrameIndex) << "\n" + << "isLiveIn : " << MBlazeFI->isLiveIn(FrameIndex) << "\n" + << "isSpill : " << MFI->isSpillSlotObjectIndex(FrameIndex) + << "\n" ); // as explained on LowerFormalArguments, detect negative offsets // and adjust SPOffsets considering the final stack size. - int Offset = (spOffset < 0) ? (stackSize - spOffset) : (spOffset + 4); - Offset += MI.getOperand(oi).getImm(); + int Offset = (spOffset < 0) ? (stackSize - spOffset) : spOffset; + Offset += MI.getOperand(oi).getImm(); - DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); + DEBUG(dbgs() << "Offset : " << Offset << "\n" << "<--------->\n"); MI.getOperand(oi).ChangeToImmediate(Offset); MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false); @@ -235,7 +317,9 @@ unsigned MBlazeRegisterInfo::getRARegister() const { } unsigned MBlazeRegisterInfo::getFrameRegister(const MachineFunction &MF) const { - return hasFP(MF) ? MBlaze::R19 : MBlaze::R1; + const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); + + return TFI->hasFP(MF) ? MBlaze::R19 : MBlaze::R1; } unsigned MBlazeRegisterInfo::getEHExceptionRegister() const { @@ -248,9 +332,8 @@ unsigned MBlazeRegisterInfo::getEHHandlerRegister() const { return 0; } -int MBlazeRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { - llvm_unreachable("What is the dwarf register number"); - return -1; +int MBlazeRegisterInfo::getDwarfRegNum(unsigned RegNo, bool isEH) const { + return MBlazeGenRegisterInfo::getDwarfRegNumFull(RegNo,0); } #include "MBlazeGenRegisterInfo.inc" diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.h b/lib/Target/MBlaze/MBlazeRegisterInfo.h index 356a11f..839536d 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.h +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.h @@ -44,20 +44,16 @@ struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo { /// MBlaze::RA, return the number that it corresponds to (e.g. 31). static unsigned getRegisterNumbering(unsigned RegEnum); static unsigned getRegisterFromNumbering(unsigned RegEnum); + static unsigned getSpecialRegisterFromNumbering(unsigned RegEnum); /// Get PIC indirect call register static unsigned getPICCallReg(); - /// Adjust the MBlaze stack frame. - void adjustMBlazeStackFrame(MachineFunction &MF) const; - /// Code Generation virtual methods... const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const; BitVector getReservedRegs(const MachineFunction &MF) const; - bool hasFP(const MachineFunction &MF) const; - void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.td b/lib/Target/MBlaze/MBlazeRegisterInfo.td index 7a49192..fbefb22 100644 --- a/lib/Target/MBlaze/MBlazeRegisterInfo.td +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.td @@ -17,25 +17,27 @@ class MBlazeReg<string n> : Register<n> { let Namespace = "MBlaze"; } -// MBlaze CPU Registers +// Special purpose registers have 15-bit values +class MBlazeSReg<string n> : Register<n> { + field bits<15> Num; + let Namespace = "MBlaze"; +} + +// MBlaze general purpose registers class MBlazeGPRReg<bits<5> num, string n> : MBlazeReg<n> { let Num = num; } -// MBlaze 32-bit (aliased) FPU Registers -/* -class FPR<bits<5> num, string n, list<Register> aliases> : MBlazeReg<n> { +// MBlaze special purpose registers +class MBlazeSPRReg<bits<15> num, string n> : MBlazeSReg<n> { let Num = num; - let Aliases = aliases; } -*/ //===----------------------------------------------------------------------===// // Registers //===----------------------------------------------------------------------===// let Namespace = "MBlaze" in { - // General Purpose Registers def R0 : MBlazeGPRReg< 0, "r0">, DwarfRegNum<[0]>; def R1 : MBlazeGPRReg< 1, "r1">, DwarfRegNum<[1]>; @@ -70,41 +72,36 @@ let Namespace = "MBlaze" in { def R30 : MBlazeGPRReg< 30, "r30">, DwarfRegNum<[30]>; def R31 : MBlazeGPRReg< 31, "r31">, DwarfRegNum<[31]>; - /// MBlaze Single point precision FPU Registers - /* - def F0 : FPR< 0, "f0", [R0]>, DwarfRegNum<[32]>; - def F1 : FPR< 1, "f1", [R1]>, DwarfRegNum<[33]>; - def F2 : FPR< 2, "f2", [R2]>, DwarfRegNum<[34]>; - def F3 : FPR< 3, "f3", [R3]>, DwarfRegNum<[35]>; - def F4 : FPR< 4, "f4", [R4]>, DwarfRegNum<[36]>; - def F5 : FPR< 5, "f5", [R5]>, DwarfRegNum<[37]>; - def F6 : FPR< 6, "f6", [R6]>, DwarfRegNum<[38]>; - def F7 : FPR< 7, "f7", [R7]>, DwarfRegNum<[39]>; - def F8 : FPR< 8, "f8", [R8]>, DwarfRegNum<[40]>; - def F9 : FPR< 9, "f9", [R9]>, DwarfRegNum<[41]>; - def F10 : FPR<10, "f10", [R10]>, DwarfRegNum<[42]>; - def F11 : FPR<11, "f11", [R11]>, DwarfRegNum<[43]>; - def F12 : FPR<12, "f12", [R12]>, DwarfRegNum<[44]>; - def F13 : FPR<13, "f13", [R13]>, DwarfRegNum<[45]>; - def F14 : FPR<14, "f14", [R14]>, DwarfRegNum<[46]>; - def F15 : FPR<15, "f15", [R15]>, DwarfRegNum<[47]>; - def F16 : FPR<16, "f16", [R16]>, DwarfRegNum<[48]>; - def F17 : FPR<17, "f17", [R17]>, DwarfRegNum<[49]>; - def F18 : FPR<18, "f18", [R18]>, DwarfRegNum<[50]>; - def F19 : FPR<19, "f19", [R19]>, DwarfRegNum<[51]>; - def F20 : FPR<20, "f20", [R20]>, DwarfRegNum<[52]>; - def F21 : FPR<21, "f21", [R21]>, DwarfRegNum<[53]>; - def F22 : FPR<22, "f22", [R22]>, DwarfRegNum<[54]>; - def F23 : FPR<23, "f23", [R23]>, DwarfRegNum<[55]>; - def F24 : FPR<24, "f24", [R24]>, DwarfRegNum<[56]>; - def F25 : FPR<25, "f25", [R25]>, DwarfRegNum<[57]>; - def F26 : FPR<26, "f26", [R26]>, DwarfRegNum<[58]>; - def F27 : FPR<27, "f27", [R27]>, DwarfRegNum<[59]>; - def F28 : FPR<28, "f28", [R28]>, DwarfRegNum<[60]>; - def F29 : FPR<29, "f29", [R29]>, DwarfRegNum<[61]>; - def F30 : FPR<30, "f30", [R30]>, DwarfRegNum<[62]>; - def F31 : FPR<31, "f31", [R31]>, DwarfRegNum<[63]>; - */ + // Special Purpose Registers + def RPC : MBlazeSPRReg<0x0000, "rpc">, DwarfRegNum<[32]>; + def RMSR : MBlazeSPRReg<0x0001, "rmsr">, DwarfRegNum<[33]>; + def REAR : MBlazeSPRReg<0x0003, "rear">, DwarfRegNum<[34]>; + def RESR : MBlazeSPRReg<0x0005, "resr">, DwarfRegNum<[35]>; + def RFSR : MBlazeSPRReg<0x0007, "rfsr">, DwarfRegNum<[36]>; + def RBTR : MBlazeSPRReg<0x000B, "rbtr">, DwarfRegNum<[37]>; + def REDR : MBlazeSPRReg<0x000D, "redr">, DwarfRegNum<[38]>; + def RPID : MBlazeSPRReg<0x1000, "rpid">, DwarfRegNum<[39]>; + def RZPR : MBlazeSPRReg<0x1001, "rzpr">, DwarfRegNum<[40]>; + def RTLBX : MBlazeSPRReg<0x1002, "rtlbx">, DwarfRegNum<[41]>; + def RTLBLO : MBlazeSPRReg<0x1003, "rtlblo">, DwarfRegNum<[42]>; + def RTLBHI : MBlazeSPRReg<0x1004, "rtlbhi">, DwarfRegNum<[43]>; + def RPVR0 : MBlazeSPRReg<0x2000, "rpvr0">, DwarfRegNum<[44]>; + def RPVR1 : MBlazeSPRReg<0x2001, "rpvr1">, DwarfRegNum<[45]>; + def RPVR2 : MBlazeSPRReg<0x2002, "rpvr2">, DwarfRegNum<[46]>; + def RPVR3 : MBlazeSPRReg<0x2003, "rpvr3">, DwarfRegNum<[47]>; + def RPVR4 : MBlazeSPRReg<0x2004, "rpvr4">, DwarfRegNum<[48]>; + def RPVR5 : MBlazeSPRReg<0x2005, "rpvr5">, DwarfRegNum<[49]>; + def RPVR6 : MBlazeSPRReg<0x2006, "rpvr6">, DwarfRegNum<[50]>; + def RPVR7 : MBlazeSPRReg<0x2007, "rpvr7">, DwarfRegNum<[51]>; + def RPVR8 : MBlazeSPRReg<0x2008, "rpvr8">, DwarfRegNum<[52]>; + def RPVR9 : MBlazeSPRReg<0x2009, "rpvr9">, DwarfRegNum<[53]>; + def RPVR10 : MBlazeSPRReg<0x200A, "rpvr10">, DwarfRegNum<[54]>; + def RPVR11 : MBlazeSPRReg<0x200B, "rpvr11">, DwarfRegNum<[55]>; + + // The carry bit. In the Microblaze this is really bit 29 of the + // MSR register but this is the only bit of that register that we + // are interested in modeling. + def CARRY : MBlazeSPRReg<0x0000, "rmsr[c]">, DwarfRegNum<[33]>; } //===----------------------------------------------------------------------===// @@ -147,40 +144,47 @@ def GPR : RegisterClass<"MBlaze", [i32,f32], 32, }]; } -/* -def FGR32 : RegisterClass<"MBlaze", [f32], 32, +def SPR : RegisterClass<"MBlaze", [i32], 32, [ - // Return Values and Arguments - F3, F4, F5, F6, F7, F8, F9, F10, - - // Not preserved across procedure calls - F11, F12, - - // Callee save - F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31, - // Reserved - F0, // Always zero - F1, // The stack pointer - F2, // Read-only small data area anchor - F13, // Read-write small data area anchor - F14, // Return address for interrupts - F15, // Return address for sub-routines - F16, // Return address for trap - F17, // Return address for exceptions - F18, // Reserved for assembler - F19 // The frame pointer + RPC, + RMSR, + REAR, + RESR, + RFSR, + RBTR, + REDR, + RPID, + RZPR, + RTLBX, + RTLBLO, + RTLBHI, + RPVR0, + RPVR1, + RPVR2, + RPVR3, + RPVR4, + RPVR5, + RPVR6, + RPVR7, + RPVR8, + RPVR9, + RPVR10, + RPVR11 ]> { let MethodProtos = [{ iterator allocation_order_end(const MachineFunction &MF) const; }]; let MethodBodies = [{ - FGR32Class::iterator - FGR32Class::allocation_order_end(const MachineFunction &MF) const { - // The last 10 registers on the list above are reserved - return end()-10; + SPRClass::iterator + SPRClass::allocation_order_end(const MachineFunction &MF) const { + // None of the special purpose registers are allocatable. + return end()-24; } }]; } -*/ + +def CRC : RegisterClass<"MBlaze", [i32], 32, [CARRY]> { + let CopyCost = -1; +} diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.cpp b/lib/Target/MBlaze/MBlazeTargetMachine.cpp index 7b0f9bb..cd949e1 100644 --- a/lib/Target/MBlaze/MBlazeTargetMachine.cpp +++ b/lib/Target/MBlaze/MBlazeTargetMachine.cpp @@ -33,20 +33,21 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, - bool RelaxAll) { + bool RelaxAll, + bool NoExecStack) { Triple TheTriple(TT); switch (TheTriple.getOS()) { case Triple::Darwin: llvm_unreachable("MBlaze does not support Darwin MACH-O format"); return NULL; case Triple::MinGW32: - case Triple::MinGW64: case Triple::Cygwin: case Triple::Win32: - llvm_unreachable("ARM does not support Windows COFF format"); + llvm_unreachable("MBlaze does not support Windows COFF format"); return NULL; default: - return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll); + return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll, + NoExecStack); } } @@ -85,7 +86,7 @@ MBlazeTargetMachine(const Target &T, const std::string &TT, Subtarget(TT, FS), DataLayout("E-p:32:32:32-i8:8:8-i16:16:16"), InstrInfo(*this), - FrameInfo(Subtarget), + FrameLowering(Subtarget), TLInfo(*this), TSInfo(*this), ELFWriterInfo(*this) { if (getRelocationModel() == Reloc::Default) { setRelocationModel(Reloc::Static); @@ -97,8 +98,8 @@ MBlazeTargetMachine(const Target &T, const std::string &TT, // Install an instruction selector pass using // the ISelDag to gen MBlaze code. -bool MBlazeTargetMachine:: -addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { +bool MBlazeTargetMachine::addInstSelector(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { PM.add(createMBlazeISelDag(*this)); return false; } @@ -106,8 +107,8 @@ addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { // Implemented by targets that want to run passes immediately before // machine code is emitted. return true if -print-machineinstrs should // print out the code after the passes. -bool MBlazeTargetMachine:: -addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { +bool MBlazeTargetMachine::addPreEmitPass(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { PM.add(createMBlazeDelaySlotFillerPass(*this)); return true; } diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.h b/lib/Target/MBlaze/MBlazeTargetMachine.h index 12573d8..45ad078 100644 --- a/lib/Target/MBlaze/MBlazeTargetMachine.h +++ b/lib/Target/MBlaze/MBlazeTargetMachine.h @@ -19,24 +19,24 @@ #include "MBlazeISelLowering.h" #include "MBlazeSelectionDAGInfo.h" #include "MBlazeIntrinsicInfo.h" -#include "MBlazeFrameInfo.h" +#include "MBlazeFrameLowering.h" #include "MBlazeELFWriterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetFrameLowering.h" namespace llvm { class formatted_raw_ostream; class MBlazeTargetMachine : public LLVMTargetMachine { - MBlazeSubtarget Subtarget; - const TargetData DataLayout; // Calculates type size & alignment - MBlazeInstrInfo InstrInfo; - MBlazeFrameInfo FrameInfo; - MBlazeTargetLowering TLInfo; + MBlazeSubtarget Subtarget; + const TargetData DataLayout; // Calculates type size & alignment + MBlazeInstrInfo InstrInfo; + MBlazeFrameLowering FrameLowering; + MBlazeTargetLowering TLInfo; MBlazeSelectionDAGInfo TSInfo; - MBlazeIntrinsicInfo IntrinsicInfo; + MBlazeIntrinsicInfo IntrinsicInfo; MBlazeELFWriterInfo ELFWriterInfo; public: MBlazeTargetMachine(const Target &T, const std::string &TT, @@ -45,8 +45,8 @@ namespace llvm { virtual const MBlazeInstrInfo *getInstrInfo() const { return &InstrInfo; } - virtual const TargetFrameInfo *getFrameInfo() const - { return &FrameInfo; } + virtual const TargetFrameLowering *getFrameLowering() const + { return &FrameLowering; } virtual const MBlazeSubtarget *getSubtargetImpl() const { return &Subtarget; } @@ -71,11 +71,8 @@ namespace llvm { } // Pass Pipeline Configuration - virtual bool addInstSelector(PassManagerBase &PM, - CodeGenOpt::Level OptLevel); - - virtual bool addPreEmitPass(PassManagerBase &PM, - CodeGenOpt::Level OptLevel); + virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level Opt); + virtual bool addPreEmitPass(PassManagerBase &PM,CodeGenOpt::Level Opt); }; } // End llvm namespace diff --git a/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp b/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp index 05c01ef..abd1b0b 100644 --- a/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp +++ b/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp @@ -16,6 +16,7 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ELF.h" using namespace llvm; void MBlazeTargetObjectFile:: @@ -23,13 +24,13 @@ Initialize(MCContext &Ctx, const TargetMachine &TM) { TargetLoweringObjectFileELF::Initialize(Ctx, TM); SmallDataSection = - getContext().getELFSection(".sdata", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC, + getContext().getELFSection(".sdata", ELF::SHT_PROGBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, SectionKind::getDataRel()); SmallBSSSection = - getContext().getELFSection(".sbss", MCSectionELF::SHT_NOBITS, - MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC, + getContext().getELFSection(".sbss", ELF::SHT_NOBITS, + ELF::SHF_WRITE |ELF::SHF_ALLOC, SectionKind::getBSS()); } diff --git a/lib/Target/MBlaze/Makefile b/lib/Target/MBlaze/Makefile index 0150604..e01c60b 100644 --- a/lib/Target/MBlaze/Makefile +++ b/lib/Target/MBlaze/Makefile @@ -12,12 +12,12 @@ TARGET = MBlaze # Make sure that tblgen is run, first thing. BUILT_SOURCES = MBlazeGenRegisterInfo.h.inc MBlazeGenRegisterNames.inc \ - MBlazeGenRegisterInfo.inc MBlazeGenInstrNames.inc \ - MBlazeGenInstrInfo.inc MBlazeGenAsmWriter.inc \ - MBlazeGenDAGISel.inc MBlazeGenAsmMatcher.inc \ - MBlazeGenCodeEmitter.inc MBlazeGenCallingConv.inc \ - MBlazeGenSubtarget.inc MBlazeGenIntrinsics.inc \ - MBlazeGenEDInfo.inc + MBlazeGenRegisterInfo.inc MBlazeGenInstrNames.inc \ + MBlazeGenInstrInfo.inc MBlazeGenAsmWriter.inc \ + MBlazeGenDAGISel.inc MBlazeGenAsmMatcher.inc \ + MBlazeGenCodeEmitter.inc MBlazeGenCallingConv.inc \ + MBlazeGenSubtarget.inc MBlazeGenIntrinsics.inc \ + MBlazeGenEDInfo.inc DIRS = InstPrinter AsmParser Disassembler TargetInfo diff --git a/lib/Target/MBlaze/TODO b/lib/Target/MBlaze/TODO index cc0aa48..2e613eb 100644 --- a/lib/Target/MBlaze/TODO +++ b/lib/Target/MBlaze/TODO @@ -1,30 +1,14 @@ * Writing out ELF files is close to working but the following needs to be examined more closely: - - ELF relocation records are incorrect because the function - ELFObjectWriter::RecordRelocation is hard coded for X86/X86-64. - Relocations use 2-byte / 4-byte to terminology in reference to the size of the immediate value being changed. The Xilinx terminology seems to be (???) 4-byte / 8-byte in reference to the number of bytes of instructions that are being changed. - - BRLID and like instructions are always assumed to use a 4-byte - immediate value for the relocation and BEQID and like instructions - are always assumed to use a 2-byte immediate value for the relocation. - I think this means that conditional branches like BEQID can only - branch += 32768 bytes (~8192 instructions). We should allow conditional - branches to use 4-byte relocations but I'm not sure how to do that - right now. - - Relocation records for indirect calls are not being generated - correctly. These should emit and IMM 0 directly before the ORI - instruction that loads the register (just like when a BRLID - instruction is used instead of an ORI). * Code generation seems to work relatively well now but the following needs to be examined more closely: - The stack layout needs to be examined to make sure it meets the standard, especially in regards to var arg functions. - - The delay slot filler is ad hoc but seems to work. Load and - store instructions were prevented from being moved to delay - slots but I'm not sure that is necessary. - The processor itineraries are copied from a different backend and need to be updated to model the MicroBlaze correctly. - Look at the MBlazeGenFastISel.inc stuff and make use of it |