X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FPowerPC%2FPPCCodeEmitter.cpp;h=f09a42a70392ed70f78f202eb42b26b171d51ab9;hb=9ba12359e3b4ca5bce5469d86ae38eb1237752ee;hp=e33c8c133e3715356c1097b5939631d854c979c7;hpb=c982cfad875f64284ae0fb2f822b0867657171eb;p=oota-llvm.git diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp index e33c8c133e3..f09a42a7039 100644 --- a/lib/Target/PowerPC/PPCCodeEmitter.cpp +++ b/lib/Target/PowerPC/PPCCodeEmitter.cpp @@ -12,21 +12,35 @@ // //===----------------------------------------------------------------------===// -#include "PPC32JITInfo.h" #include "PPC32TargetMachine.h" +#include "PPC32Relocations.h" +#include "PowerPC.h" +#include "llvm/Module.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/Passes.h" #include "llvm/Support/Debug.h" - -namespace llvm { +using namespace llvm; namespace { class PPC32CodeEmitter : public MachineFunctionPass { TargetMachine &TM; MachineCodeEmitter &MCE; - int64_t getMachineOpValue(MachineInstr &MI, MachineOperand &MO); + /// MovePCtoLROffset - When/if we see a MovePCtoLR instruction, we record + /// its address in the function into this pointer. + void *MovePCtoLROffset; + + // Tracks which instruction references which BasicBlock + std::vector > > BBRefs; + // Tracks where each BasicBlock starts + std::map BBLocations; + + /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr + /// + int getMachineOpValue(MachineInstr &MI, MachineOperand &MO); public: PPC32CodeEmitter(TargetMachine &T, MachineCodeEmitter &M) @@ -50,7 +64,9 @@ namespace { /// unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; } - /// getBinaryCodeForInstr - returns the assembled code for an instruction + /// getBinaryCodeForInstr - This function, generated by the + /// CodeEmitterGenerator using TableGen, produces the binary encoding for + /// machine instructions. /// unsigned getBinaryCodeForInstr(MachineInstr &MI); }; @@ -72,62 +88,154 @@ bool PPC32TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM, } bool PPC32CodeEmitter::runOnMachineFunction(MachineFunction &MF) { + MovePCtoLROffset = 0; MCE.startFunction(MF); MCE.emitConstantPool(MF.getConstantPool()); - for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) - emitBasicBlock(*I); + for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB) + emitBasicBlock(*BB); MCE.finishFunction(MF); + + // Resolve branches to BasicBlocks for the entire function + for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) { + intptr_t Location = BBLocations[BBRefs[i].first]; + unsigned *Ref = BBRefs[i].second.first; + MachineInstr *MI = BBRefs[i].second.second; + DEBUG(std::cerr << "Fixup @ " << (void*)Ref << " to " << (void*)Location + << " in instr: " << *MI); + for (unsigned ii = 0, ee = MI->getNumOperands(); ii != ee; ++ii) { + MachineOperand &op = MI->getOperand(ii); + if (op.isPCRelativeDisp()) { + // the instruction's branch target is made such that it branches to + // PC + (branchTarget * 4), so undo that arithmetic here: + // Location is the target of the branch + // Ref is the location of the instruction, and hence the PC + int64_t branchTarget = (Location - (long)Ref) >> 2; + MI->SetMachineOperandConst(ii, MachineOperand::MO_SignExtendedImmed, + branchTarget); + unsigned fixedInstr = PPC32CodeEmitter::getBinaryCodeForInstr(*MI); + MCE.emitWordAt(fixedInstr, Ref); + break; + } + } + } + BBRefs.clear(); + BBLocations.clear(); + return false; } void PPC32CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) { - for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I) - emitWord(getBinaryCodeForInstr(*I)); + BBLocations[MBB.getBasicBlock()] = MCE.getCurrentPCValue(); + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){ + MachineInstr &MI = *I; + unsigned Opcode = MI.getOpcode(); + switch (MI.getOpcode()) { + default: + emitWord(getBinaryCodeForInstr(*I)); + break; + case PPC::IMPLICIT_DEF: + break; // pseudo opcode, no side effects + case PPC::MovePCtoLR: + assert(MovePCtoLROffset == 0 && + "Multiple MovePCtoLR instructions in the function?"); + MovePCtoLROffset = (void*)(intptr_t)MCE.getCurrentPCValue(); + emitWord(0x48000005); // bl 1 + break; + } + } } -int64_t PPC32CodeEmitter::getMachineOpValue(MachineInstr &MI, - MachineOperand &MO) { - int64_t rv = 0; // Return value; defaults to 0 for unhandled cases - // or things that get fixed up later by the JIT. - if (MO.isPCRelativeDisp()) { - std::cerr << "PPC32CodeEmitter: PC-relative disp unhandled\n"; +static unsigned enumRegToMachineReg(unsigned enumReg) { + switch (enumReg) { + case PPC::R0 : case PPC::F0 : case PPC::CR0: return 0; + case PPC::R1 : case PPC::F1 : case PPC::CR1: return 1; + case PPC::R2 : case PPC::F2 : case PPC::CR2: return 2; + case PPC::R3 : case PPC::F3 : case PPC::CR3: return 3; + case PPC::R4 : case PPC::F4 : case PPC::CR4: return 4; + case PPC::R5 : case PPC::F5 : case PPC::CR5: return 5; + case PPC::R6 : case PPC::F6 : case PPC::CR6: return 6; + case PPC::R7 : case PPC::F7 : case PPC::CR7: return 7; + case PPC::R8 : case PPC::F8 : return 8; + case PPC::R9 : case PPC::F9 : return 9; + case PPC::R10: case PPC::F10: return 10; + case PPC::R11: case PPC::F11: return 11; + case PPC::R12: case PPC::F12: return 12; + case PPC::R13: case PPC::F13: return 13; + case PPC::R14: case PPC::F14: return 14; + case PPC::R15: case PPC::F15: return 15; + case PPC::R16: case PPC::F16: return 16; + case PPC::R17: case PPC::F17: return 17; + case PPC::R18: case PPC::F18: return 18; + case PPC::R19: case PPC::F19: return 19; + case PPC::R20: case PPC::F20: return 20; + case PPC::R21: case PPC::F21: return 21; + case PPC::R22: case PPC::F22: return 22; + case PPC::R23: case PPC::F23: return 23; + case PPC::R24: case PPC::F24: return 24; + case PPC::R25: case PPC::F25: return 25; + case PPC::R26: case PPC::F26: return 26; + case PPC::R27: case PPC::F27: return 27; + case PPC::R28: case PPC::F28: return 28; + case PPC::R29: case PPC::F29: return 29; + case PPC::R30: case PPC::F30: return 30; + case PPC::R31: case PPC::F31: return 31; + default: + std::cerr << "Unhandled reg in enumRegToRealReg!\n"; abort(); - } else if (MO.isRegister()) { - rv = MO.getReg(); + } +} + +int PPC32CodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) { + + int rv = 0; // Return value; defaults to 0 for unhandled cases + // or things that get fixed up later by the JIT. + if (MO.isRegister()) { + rv = enumRegToMachineReg(MO.getReg()); } else if (MO.isImmediate()) { rv = MO.getImmedValue(); -#if 0 } else if (MO.isGlobalAddress()) { + unsigned Reloc = 0; + if (MI.getOpcode() == PPC::CALLpcrel) + Reloc = PPC::reloc_pcrel_bx; + else if (MI.getOpcode() == PPC::LOADHiAddr) { + Reloc = PPC::reloc_absolute_loadhi; + } else if (MI.getOpcode() == PPC::LA) { + Reloc = PPC::reloc_absolute_la; + } else { + assert(0 && "Unknown instruction for relocation!"); + } + MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(), + Reloc, MO.getGlobal(), + -((intptr_t)MovePCtoLROffset+4))); } else if (MO.isMachineBasicBlock()) { - MachineBasicBlock *MBB = MO.getMachineBasicBlock(); - } else if (MO.isExternalSymbol()) { - } else if (MO.isFrameIndex()) { - unsigned index = MO.getFrameIndex(); + const BasicBlock *BB = MO.getMachineBasicBlock()->getBasicBlock(); + unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue(); + BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI))); } else if (MO.isConstantPoolIndex()) { - unsigned index = MO.getCosntantPoolIndex(); -#endif + unsigned index = MO.getConstantPoolIndex(); + rv = MCE.getConstantPoolEntryAddress(index); } else { std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n"; abort(); } + // Special treatment for global symbols: constants and vars + if ((MO.isConstantPoolIndex() || MO.isGlobalAddress()) && + MI.getOpcode() != PPC::CALLpcrel) { + unsigned Opcode = MI.getOpcode(); + assert(MovePCtoLROffset && "MovePCtoLR not seen yet?"); + + if (Opcode == PPC::LOADHiAddr) { + // LoadHiAddr wants hi16(addr - &MovePCtoLR) + rv >>= 16; + } else if (Opcode == PPC::LWZ || Opcode == PPC::LA || + Opcode == PPC::LFS || Opcode == PPC::LFD) { + // These load opcodes want lo16(addr - &MovePCtoLR) + rv &= 0xffff; + } + } return rv; } - -void *PPC32JITInfo::getJITStubForFunction(Function *F, - MachineCodeEmitter &MCE) { - std::cerr << "PPC32JITInfo::getJITStubForFunction not implemented\n"; - abort(); - return 0; -} - -void PPC32JITInfo::replaceMachineCodeForFunction (void *Old, void *New) { - std::cerr << "PPC32JITInfo::replaceMachineCodeForFunction not implemented\n"; - abort(); -} - #include "PPC32GenCodeEmitter.inc" -} // end llvm namespace -