diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Mips/MipsCodeEmitter.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/Mips/MipsCodeEmitter.cpp | 223 |
1 files changed, 192 insertions, 31 deletions
diff --git a/contrib/llvm/lib/Target/Mips/MipsCodeEmitter.cpp b/contrib/llvm/lib/Target/Mips/MipsCodeEmitter.cpp index 23fabe3..7d81902 100644 --- a/contrib/llvm/lib/Target/Mips/MipsCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsCodeEmitter.cpp @@ -1,4 +1,4 @@ -//===-- Mips/MipsCodeEmitter.cpp - Convert Mips code to machine code -----===// +//===-- Mips/MipsCodeEmitter.cpp - Convert Mips Code to Machine Code ------===// // // The LLVM Compiler Infrastructure // @@ -18,18 +18,20 @@ #include "MipsRelocations.h" #include "MipsSubtarget.h" #include "MipsTargetMachine.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Function.h" -#include "llvm/PassManager.h" +#include "MCTargetDesc/MipsBaseInfo.h" +#include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/JITCodeEmitter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/ADT/Statistic.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/PassManager.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -37,8 +39,6 @@ #include <iomanip> #endif -#include "llvm/CodeGen/MachineOperand.h" - using namespace llvm; STATISTIC(NumEmitted, "Number of machine instructions emitted"); @@ -66,9 +66,9 @@ class MipsCodeEmitter : public MachineFunctionPass { public: MipsCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) : MachineFunctionPass(ID), JTI(0), - II((const MipsInstrInfo *) tm.getInstrInfo()), - TD(tm.getTargetData()), TM(tm), MCE(mce), MCPEs(0), MJTEs(0), - IsPIC(TM.getRelocationModel() == Reloc::PIC_) { + II((const MipsInstrInfo *) tm.getInstrInfo()), + TD(tm.getTargetData()), TM(tm), MCE(mce), MCPEs(0), MJTEs(0), + IsPIC(TM.getRelocationModel() == Reloc::PIC_) { } bool runOnMachineFunction(MachineFunction &MF); @@ -80,7 +80,7 @@ class MipsCodeEmitter : public MachineFunctionPass { /// getBinaryCodeForInstr - This function, generated by the /// CodeEmitterGenerator using TableGen, produces the binary encoding for /// machine instructions. - unsigned getBinaryCodeForInstr(const MachineInstr &MI) const; + uint64_t getBinaryCodeForInstr(const MachineInstr &MI) const; void emitInstruction(const MachineInstr &MI); @@ -91,7 +91,7 @@ class MipsCodeEmitter : public MachineFunctionPass { /// Routines that handle operands which add machine relocations which are /// fixed up by the relocation stage. void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, - bool MayNeedFarStub) const; + bool MayNeedFarStub) const; void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const; void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const; void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const; @@ -105,9 +105,22 @@ class MipsCodeEmitter : public MachineFunctionPass { unsigned getRelocation(const MachineInstr &MI, const MachineOperand &MO) const; + unsigned getJumpTargetOpValue(const MachineInstr &MI, unsigned OpNo) const; + + unsigned getBranchTargetOpValue(const MachineInstr &MI, + unsigned OpNo) const; unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const; unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const; + + int emitULW(const MachineInstr &MI); + int emitUSW(const MachineInstr &MI); + int emitULH(const MachineInstr &MI); + int emitULHu(const MachineInstr &MI); + int emitUSH(const MachineInstr &MI); + + void emitGlobalAddressUnaligned(const GlobalValue *GV, unsigned Reloc, + int Offset) const; }; } @@ -132,7 +145,7 @@ bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) { for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); MBB != E; ++MBB){ MCE.StartMachineBasicBlock(MBB); - for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) emitInstruction(*I); } @@ -149,30 +162,50 @@ unsigned MipsCodeEmitter::getRelocation(const MachineInstr &MI, if (Form == MipsII::FrmJ) return Mips::reloc_mips_26; if ((Form == MipsII::FrmI || Form == MipsII::FrmFI) - && MI.getDesc().isBranch()) - return Mips::reloc_mips_branch; + && MI.isBranch()) + return Mips::reloc_mips_pc16; if (Form == MipsII::FrmI && MI.getOpcode() == Mips::LUi) return Mips::reloc_mips_hi; return Mips::reloc_mips_lo; } +unsigned MipsCodeEmitter::getJumpTargetOpValue(const MachineInstr &MI, + unsigned OpNo) const { + MachineOperand MO = MI.getOperand(OpNo); + if (MO.isGlobal()) + emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true); + else if (MO.isSymbol()) + emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO)); + else if (MO.isMBB()) + emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); + else + llvm_unreachable("Unexpected jump target operand kind."); + return 0; +} + +unsigned MipsCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI, + unsigned OpNo) const { + MachineOperand MO = MI.getOperand(OpNo); + emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); + return 0; +} + unsigned MipsCodeEmitter::getMemEncoding(const MachineInstr &MI, - unsigned OpNo) const { + unsigned OpNo) const { // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. assert(MI.getOperand(OpNo).isReg()); unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo)) << 16; - return - (getMachineOpValue(MI, MI.getOperand(OpNo+1)) & 0xFFFF) | RegBits; + return (getMachineOpValue(MI, MI.getOperand(OpNo+1)) & 0xFFFF) | RegBits; } unsigned MipsCodeEmitter::getSizeExtEncoding(const MachineInstr &MI, - unsigned OpNo) const { + unsigned OpNo) const { // size is encoded as size-1. return getMachineOpValue(MI, MI.getOperand(OpNo)) - 1; } unsigned MipsCodeEmitter::getSizeInsEncoding(const MachineInstr &MI, - unsigned OpNo) const { + unsigned OpNo) const { // size is encoded as pos+size-1. return getMachineOpValue(MI, MI.getOperand(OpNo-1)) + getMachineOpValue(MI, MI.getOperand(OpNo)) - 1; @@ -181,14 +214,20 @@ unsigned MipsCodeEmitter::getSizeInsEncoding(const MachineInstr &MI, /// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI, - const MachineOperand &MO) const { + const MachineOperand &MO) const { if (MO.isReg()) - return MipsRegisterInfo::getRegisterNumbering(MO.getReg()); + return getMipsRegisterNumbering(MO.getReg()); else if (MO.isImm()) return static_cast<unsigned>(MO.getImm()); - else if (MO.isGlobal()) - emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true); - else if (MO.isSymbol()) + else if (MO.isGlobal()) { + if (MI.getOpcode() == Mips::ULW || MI.getOpcode() == Mips::USW || + MI.getOpcode() == Mips::ULH || MI.getOpcode() == Mips::ULHu) + emitGlobalAddressUnaligned(MO.getGlobal(), getRelocation(MI, MO), 4); + else if (MI.getOpcode() == Mips::USH) + emitGlobalAddressUnaligned(MO.getGlobal(), getRelocation(MI, MO), 8); + else + emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true); + } else if (MO.isSymbol()) emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO)); else if (MO.isCPI()) emitConstPoolAddress(MO.getIndex(), getRelocation(MI, MO)); @@ -202,9 +241,18 @@ unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI, } void MipsCodeEmitter::emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, - bool MayNeedFarStub) const { + bool MayNeedFarStub) const { MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, - const_cast<GlobalValue *>(GV), 0, MayNeedFarStub)); + const_cast<GlobalValue *>(GV), 0, + MayNeedFarStub)); +} + +void MipsCodeEmitter::emitGlobalAddressUnaligned(const GlobalValue *GV, + unsigned Reloc, int Offset) const { + MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, + const_cast<GlobalValue *>(GV), 0, false)); + MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset() + Offset, + Reloc, const_cast<GlobalValue *>(GV), 0, false)); } void MipsCodeEmitter:: @@ -225,11 +273,108 @@ emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const { } void MipsCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB, - unsigned Reloc) const { + unsigned Reloc) const { MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), Reloc, BB)); } +int MipsCodeEmitter::emitUSW(const MachineInstr &MI) { + unsigned src = getMachineOpValue(MI, MI.getOperand(0)); + unsigned base = getMachineOpValue(MI, MI.getOperand(1)); + unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); + // swr src, offset(base) + // swl src, offset+3(base) + MCE.emitWordLE( + (0x2e << 26) | (base << 21) | (src << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x2a << 26) | (base << 21) | (src << 16) | ((offset+3) & 0xffff)); + return 2; +} + +int MipsCodeEmitter::emitULW(const MachineInstr &MI) { + unsigned dst = getMachineOpValue(MI, MI.getOperand(0)); + unsigned base = getMachineOpValue(MI, MI.getOperand(1)); + unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); + unsigned at = 1; + if (dst != base) { + // lwr dst, offset(base) + // lwl dst, offset+3(base) + MCE.emitWordLE( + (0x26 << 26) | (base << 21) | (dst << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x22 << 26) | (base << 21) | (dst << 16) | ((offset+3) & 0xffff)); + return 2; + } else { + // lwr at, offset(base) + // lwl at, offset+3(base) + // addu dst, at, $zero + MCE.emitWordLE( + (0x26 << 26) | (base << 21) | (at << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x22 << 26) | (base << 21) | (at << 16) | ((offset+3) & 0xffff)); + MCE.emitWordLE( + (0x0 << 26) | (at << 21) | (0x0 << 16) | (dst << 11) | (0x0 << 6) | 0x21); + return 3; + } +} + +int MipsCodeEmitter::emitUSH(const MachineInstr &MI) { + unsigned src = getMachineOpValue(MI, MI.getOperand(0)); + unsigned base = getMachineOpValue(MI, MI.getOperand(1)); + unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); + unsigned at = 1; + // sb src, offset(base) + // srl at,src,8 + // sb at, offset+1(base) + MCE.emitWordLE( + (0x28 << 26) | (base << 21) | (src << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x0 << 26) | (0x0 << 21) | (src << 16) | (at << 11) | (0x8 << 6) | 0x2); + MCE.emitWordLE( + (0x28 << 26) | (base << 21) | (at << 16) | ((offset+1) & 0xffff)); + return 3; +} + +int MipsCodeEmitter::emitULH(const MachineInstr &MI) { + unsigned dst = getMachineOpValue(MI, MI.getOperand(0)); + unsigned base = getMachineOpValue(MI, MI.getOperand(1)); + unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); + unsigned at = 1; + // lbu at, offset(base) + // lb dst, offset+1(base) + // sll dst,dst,8 + // or dst,dst,at + MCE.emitWordLE( + (0x24 << 26) | (base << 21) | (at << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x20 << 26) | (base << 21) | (dst << 16) | ((offset+1) & 0xffff)); + MCE.emitWordLE( + (0x0 << 26) | (0x0 << 21) | (dst << 16) | (dst << 11) | (0x8 << 6) | 0x0); + MCE.emitWordLE( + (0x0 << 26) | (dst << 21) | (at << 16) | (dst << 11) | (0x0 << 6) | 0x25); + return 4; +} + +int MipsCodeEmitter::emitULHu(const MachineInstr &MI) { + unsigned dst = getMachineOpValue(MI, MI.getOperand(0)); + unsigned base = getMachineOpValue(MI, MI.getOperand(1)); + unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); + unsigned at = 1; + // lbu at, offset(base) + // lbu dst, offset+1(base) + // sll dst,dst,8 + // or dst,dst,at + MCE.emitWordLE( + (0x24 << 26) | (base << 21) | (at << 16) | (offset & 0xffff)); + MCE.emitWordLE( + (0x24 << 26) | (base << 21) | (dst << 16) | ((offset+1) & 0xffff)); + MCE.emitWordLE( + (0x0 << 26) | (0x0 << 21) | (dst << 16) | (dst << 11) | (0x8 << 6) | 0x0); + MCE.emitWordLE( + (0x0 << 26) | (dst << 21) | (at << 16) | (dst << 11) | (0x0 << 6) | 0x25); + return 4; +} + void MipsCodeEmitter::emitInstruction(const MachineInstr &MI) { DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI); @@ -239,11 +384,27 @@ void MipsCodeEmitter::emitInstruction(const MachineInstr &MI) { if ((MI.getDesc().TSFlags & MipsII::FormMask) == MipsII::Pseudo) return; - ++NumEmitted; // Keep track of the # of mi's emitted switch (MI.getOpcode()) { + case Mips::USW: + NumEmitted += emitUSW(MI); + break; + case Mips::ULW: + NumEmitted += emitULW(MI); + break; + case Mips::ULH: + NumEmitted += emitULH(MI); + break; + case Mips::ULHu: + NumEmitted += emitULHu(MI); + break; + case Mips::USH: + NumEmitted += emitUSH(MI); + break; + default: emitWordLE(getBinaryCodeForInstr(MI)); + ++NumEmitted; // Keep track of the # of mi's emitted break; } @@ -259,7 +420,7 @@ void MipsCodeEmitter::emitWordLE(unsigned Word) { /// createMipsJITCodeEmitterPass - Return a pass that emits the collected Mips /// code to the specified MCE object. FunctionPass *llvm::createMipsJITCodeEmitterPass(MipsTargetMachine &TM, - JITCodeEmitter &JCE) { + JITCodeEmitter &JCE) { return new MipsCodeEmitter(TM, JCE); } |