MipsCodeEmitter.cpp revision 243830
1234353Sdim//===-- Mips/MipsCodeEmitter.cpp - Convert Mips Code to Machine Code ------===// 2226584Sdim// 3226584Sdim// The LLVM Compiler Infrastructure 4226584Sdim// 5226584Sdim// This file is distributed under the University of Illinois Open Source 6226584Sdim// License. See LICENSE.TXT for details. 7226584Sdim// 8226584Sdim//===---------------------------------------------------------------------===// 9226584Sdim// 10226584Sdim// This file contains the pass that transforms the Mips machine instructions 11226584Sdim// into relocatable machine code. 12226584Sdim// 13226584Sdim//===---------------------------------------------------------------------===// 14226584Sdim 15226584Sdim#define DEBUG_TYPE "jit" 16226584Sdim#include "Mips.h" 17226584Sdim#include "MipsInstrInfo.h" 18226584Sdim#include "MipsRelocations.h" 19226584Sdim#include "MipsSubtarget.h" 20226584Sdim#include "MipsTargetMachine.h" 21234353Sdim#include "MCTargetDesc/MipsBaseInfo.h" 22234353Sdim#include "llvm/ADT/Statistic.h" 23226584Sdim#include "llvm/CodeGen/JITCodeEmitter.h" 24226584Sdim#include "llvm/CodeGen/MachineConstantPool.h" 25226584Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 26226584Sdim#include "llvm/CodeGen/MachineInstr.h" 27226584Sdim#include "llvm/CodeGen/MachineJumpTableInfo.h" 28226584Sdim#include "llvm/CodeGen/MachineModuleInfo.h" 29234353Sdim#include "llvm/CodeGen/MachineOperand.h" 30226584Sdim#include "llvm/CodeGen/Passes.h" 31234353Sdim#include "llvm/Constants.h" 32234353Sdim#include "llvm/DerivedTypes.h" 33234353Sdim#include "llvm/PassManager.h" 34226584Sdim#include "llvm/Support/Debug.h" 35226584Sdim#include "llvm/Support/ErrorHandling.h" 36226584Sdim#include "llvm/Support/raw_ostream.h" 37226584Sdim#ifndef NDEBUG 38226584Sdim#include <iomanip> 39226584Sdim#endif 40226584Sdim 41226584Sdimusing namespace llvm; 42226584Sdim 43226584SdimSTATISTIC(NumEmitted, "Number of machine instructions emitted"); 44226584Sdim 45226584Sdimnamespace { 46226584Sdim 47226584Sdimclass MipsCodeEmitter : public MachineFunctionPass { 48226584Sdim MipsJITInfo *JTI; 49226584Sdim const MipsInstrInfo *II; 50243830Sdim const DataLayout *TD; 51226584Sdim const MipsSubtarget *Subtarget; 52226584Sdim TargetMachine &TM; 53226584Sdim JITCodeEmitter &MCE; 54226584Sdim const std::vector<MachineConstantPoolEntry> *MCPEs; 55226584Sdim const std::vector<MachineJumpTableEntry> *MJTEs; 56226584Sdim bool IsPIC; 57226584Sdim 58226584Sdim void getAnalysisUsage(AnalysisUsage &AU) const { 59226584Sdim AU.addRequired<MachineModuleInfo> (); 60226584Sdim MachineFunctionPass::getAnalysisUsage(AU); 61226584Sdim } 62226584Sdim 63226584Sdim static char ID; 64226584Sdim 65226584Sdim public: 66226584Sdim MipsCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce) : 67226584Sdim MachineFunctionPass(ID), JTI(0), 68234353Sdim II((const MipsInstrInfo *) tm.getInstrInfo()), 69243830Sdim TD(tm.getDataLayout()), TM(tm), MCE(mce), MCPEs(0), MJTEs(0), 70234353Sdim IsPIC(TM.getRelocationModel() == Reloc::PIC_) { 71226584Sdim } 72226584Sdim 73226584Sdim bool runOnMachineFunction(MachineFunction &MF); 74226584Sdim 75226584Sdim virtual const char *getPassName() const { 76226584Sdim return "Mips Machine Code Emitter"; 77226584Sdim } 78226584Sdim 79226584Sdim /// getBinaryCodeForInstr - This function, generated by the 80226584Sdim /// CodeEmitterGenerator using TableGen, produces the binary encoding for 81226584Sdim /// machine instructions. 82234353Sdim uint64_t getBinaryCodeForInstr(const MachineInstr &MI) const; 83226584Sdim 84226584Sdim void emitInstruction(const MachineInstr &MI); 85226584Sdim 86226584Sdim private: 87226584Sdim 88226584Sdim void emitWordLE(unsigned Word); 89226584Sdim 90226584Sdim /// Routines that handle operands which add machine relocations which are 91226584Sdim /// fixed up by the relocation stage. 92226584Sdim void emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, 93234353Sdim bool MayNeedFarStub) const; 94226584Sdim void emitExternalSymbolAddress(const char *ES, unsigned Reloc) const; 95226584Sdim void emitConstPoolAddress(unsigned CPI, unsigned Reloc) const; 96226584Sdim void emitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const; 97226584Sdim void emitMachineBasicBlock(MachineBasicBlock *BB, unsigned Reloc) const; 98226584Sdim 99226584Sdim /// getMachineOpValue - Return binary encoding of operand. If the machine 100226584Sdim /// operand requires relocation, record the relocation and return zero. 101226584Sdim unsigned getMachineOpValue(const MachineInstr &MI, 102226584Sdim const MachineOperand &MO) const; 103226584Sdim 104226584Sdim unsigned getRelocation(const MachineInstr &MI, 105226584Sdim const MachineOperand &MO) const; 106226584Sdim 107234353Sdim unsigned getJumpTargetOpValue(const MachineInstr &MI, unsigned OpNo) const; 108234353Sdim 109234353Sdim unsigned getBranchTargetOpValue(const MachineInstr &MI, 110234353Sdim unsigned OpNo) const; 111228379Sdim unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const; 112228379Sdim unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const; 113228379Sdim unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const; 114234353Sdim 115234353Sdim int emitULW(const MachineInstr &MI); 116234353Sdim int emitUSW(const MachineInstr &MI); 117234353Sdim int emitULH(const MachineInstr &MI); 118234353Sdim int emitULHu(const MachineInstr &MI); 119234353Sdim int emitUSH(const MachineInstr &MI); 120234353Sdim 121234353Sdim void emitGlobalAddressUnaligned(const GlobalValue *GV, unsigned Reloc, 122234353Sdim int Offset) const; 123226584Sdim }; 124226584Sdim} 125226584Sdim 126226584Sdimchar MipsCodeEmitter::ID = 0; 127226584Sdim 128226584Sdimbool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) { 129226584Sdim JTI = ((MipsTargetMachine&) MF.getTarget()).getJITInfo(); 130226584Sdim II = ((const MipsTargetMachine&) MF.getTarget()).getInstrInfo(); 131243830Sdim TD = ((const MipsTargetMachine&) MF.getTarget()).getDataLayout(); 132226584Sdim Subtarget = &TM.getSubtarget<MipsSubtarget> (); 133226584Sdim MCPEs = &MF.getConstantPool()->getConstants(); 134226584Sdim MJTEs = 0; 135226584Sdim if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables(); 136226584Sdim JTI->Initialize(MF, IsPIC); 137226584Sdim MCE.setModuleInfo(&getAnalysis<MachineModuleInfo> ()); 138226584Sdim 139226584Sdim do { 140226584Sdim DEBUG(errs() << "JITTing function '" 141243830Sdim << MF.getName() << "'\n"); 142226584Sdim MCE.startFunction(MF); 143226584Sdim 144226584Sdim for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); 145226584Sdim MBB != E; ++MBB){ 146226584Sdim MCE.StartMachineBasicBlock(MBB); 147239462Sdim for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(), 148239462Sdim E = MBB->instr_end(); I != E; ++I) 149226584Sdim emitInstruction(*I); 150226584Sdim } 151226584Sdim } while (MCE.finishFunction(MF)); 152226584Sdim 153226584Sdim return false; 154226584Sdim} 155226584Sdim 156226584Sdimunsigned MipsCodeEmitter::getRelocation(const MachineInstr &MI, 157226584Sdim const MachineOperand &MO) const { 158226584Sdim // NOTE: This relocations are for static. 159226584Sdim uint64_t TSFlags = MI.getDesc().TSFlags; 160226584Sdim uint64_t Form = TSFlags & MipsII::FormMask; 161226584Sdim if (Form == MipsII::FrmJ) 162226584Sdim return Mips::reloc_mips_26; 163226584Sdim if ((Form == MipsII::FrmI || Form == MipsII::FrmFI) 164234353Sdim && MI.isBranch()) 165234353Sdim return Mips::reloc_mips_pc16; 166226584Sdim if (Form == MipsII::FrmI && MI.getOpcode() == Mips::LUi) 167226584Sdim return Mips::reloc_mips_hi; 168226584Sdim return Mips::reloc_mips_lo; 169226584Sdim} 170226584Sdim 171234353Sdimunsigned MipsCodeEmitter::getJumpTargetOpValue(const MachineInstr &MI, 172234353Sdim unsigned OpNo) const { 173234353Sdim MachineOperand MO = MI.getOperand(OpNo); 174234353Sdim if (MO.isGlobal()) 175234353Sdim emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true); 176234353Sdim else if (MO.isSymbol()) 177234353Sdim emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO)); 178234353Sdim else if (MO.isMBB()) 179234353Sdim emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); 180234353Sdim else 181234353Sdim llvm_unreachable("Unexpected jump target operand kind."); 182234353Sdim return 0; 183234353Sdim} 184234353Sdim 185234353Sdimunsigned MipsCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI, 186234353Sdim unsigned OpNo) const { 187234353Sdim MachineOperand MO = MI.getOperand(OpNo); 188234353Sdim emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); 189234353Sdim return 0; 190234353Sdim} 191234353Sdim 192228379Sdimunsigned MipsCodeEmitter::getMemEncoding(const MachineInstr &MI, 193234353Sdim unsigned OpNo) const { 194228379Sdim // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. 195228379Sdim assert(MI.getOperand(OpNo).isReg()); 196228379Sdim unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo)) << 16; 197234353Sdim return (getMachineOpValue(MI, MI.getOperand(OpNo+1)) & 0xFFFF) | RegBits; 198228379Sdim} 199228379Sdim 200228379Sdimunsigned MipsCodeEmitter::getSizeExtEncoding(const MachineInstr &MI, 201234353Sdim unsigned OpNo) const { 202228379Sdim // size is encoded as size-1. 203228379Sdim return getMachineOpValue(MI, MI.getOperand(OpNo)) - 1; 204228379Sdim} 205228379Sdim 206228379Sdimunsigned MipsCodeEmitter::getSizeInsEncoding(const MachineInstr &MI, 207234353Sdim unsigned OpNo) const { 208228379Sdim // size is encoded as pos+size-1. 209228379Sdim return getMachineOpValue(MI, MI.getOperand(OpNo-1)) + 210228379Sdim getMachineOpValue(MI, MI.getOperand(OpNo)) - 1; 211228379Sdim} 212228379Sdim 213226584Sdim/// getMachineOpValue - Return binary encoding of operand. If the machine 214226584Sdim/// operand requires relocation, record the relocation and return zero. 215226584Sdimunsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI, 216234353Sdim const MachineOperand &MO) const { 217226584Sdim if (MO.isReg()) 218234353Sdim return getMipsRegisterNumbering(MO.getReg()); 219226584Sdim else if (MO.isImm()) 220226584Sdim return static_cast<unsigned>(MO.getImm()); 221243830Sdim else if (MO.isGlobal()) 222243830Sdim emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true); 223243830Sdim else if (MO.isSymbol()) 224226584Sdim emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO)); 225226584Sdim else if (MO.isCPI()) 226226584Sdim emitConstPoolAddress(MO.getIndex(), getRelocation(MI, MO)); 227226584Sdim else if (MO.isJTI()) 228226584Sdim emitJumpTableAddress(MO.getIndex(), getRelocation(MI, MO)); 229226584Sdim else if (MO.isMBB()) 230226584Sdim emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); 231226584Sdim else 232226584Sdim llvm_unreachable("Unable to encode MachineOperand!"); 233226584Sdim return 0; 234226584Sdim} 235226584Sdim 236226584Sdimvoid MipsCodeEmitter::emitGlobalAddress(const GlobalValue *GV, unsigned Reloc, 237234353Sdim bool MayNeedFarStub) const { 238226584Sdim MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, 239234353Sdim const_cast<GlobalValue *>(GV), 0, 240234353Sdim MayNeedFarStub)); 241226584Sdim} 242226584Sdim 243234353Sdimvoid MipsCodeEmitter::emitGlobalAddressUnaligned(const GlobalValue *GV, 244234353Sdim unsigned Reloc, int Offset) const { 245234353Sdim MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc, 246234353Sdim const_cast<GlobalValue *>(GV), 0, false)); 247234353Sdim MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset() + Offset, 248234353Sdim Reloc, const_cast<GlobalValue *>(GV), 0, false)); 249234353Sdim} 250234353Sdim 251226584Sdimvoid MipsCodeEmitter:: 252226584SdimemitExternalSymbolAddress(const char *ES, unsigned Reloc) const { 253226584Sdim MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(), 254239462Sdim Reloc, ES, 0, 0)); 255226584Sdim} 256226584Sdim 257226584Sdimvoid MipsCodeEmitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc) const { 258226584Sdim MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(), 259226584Sdim Reloc, CPI, 0, false)); 260226584Sdim} 261226584Sdim 262226584Sdimvoid MipsCodeEmitter:: 263226584SdimemitJumpTableAddress(unsigned JTIndex, unsigned Reloc) const { 264226584Sdim MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(), 265226584Sdim Reloc, JTIndex, 0, false)); 266226584Sdim} 267226584Sdim 268226584Sdimvoid MipsCodeEmitter::emitMachineBasicBlock(MachineBasicBlock *BB, 269234353Sdim unsigned Reloc) const { 270226584Sdim MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), 271226584Sdim Reloc, BB)); 272226584Sdim} 273226584Sdim 274234353Sdimint MipsCodeEmitter::emitUSW(const MachineInstr &MI) { 275234353Sdim unsigned src = getMachineOpValue(MI, MI.getOperand(0)); 276234353Sdim unsigned base = getMachineOpValue(MI, MI.getOperand(1)); 277234353Sdim unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); 278234353Sdim // swr src, offset(base) 279234353Sdim // swl src, offset+3(base) 280234353Sdim MCE.emitWordLE( 281234353Sdim (0x2e << 26) | (base << 21) | (src << 16) | (offset & 0xffff)); 282234353Sdim MCE.emitWordLE( 283234353Sdim (0x2a << 26) | (base << 21) | (src << 16) | ((offset+3) & 0xffff)); 284234353Sdim return 2; 285234353Sdim} 286234353Sdim 287234353Sdimint MipsCodeEmitter::emitULW(const MachineInstr &MI) { 288234353Sdim unsigned dst = getMachineOpValue(MI, MI.getOperand(0)); 289234353Sdim unsigned base = getMachineOpValue(MI, MI.getOperand(1)); 290234353Sdim unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); 291234353Sdim unsigned at = 1; 292234353Sdim if (dst != base) { 293234353Sdim // lwr dst, offset(base) 294234353Sdim // lwl dst, offset+3(base) 295234353Sdim MCE.emitWordLE( 296234353Sdim (0x26 << 26) | (base << 21) | (dst << 16) | (offset & 0xffff)); 297234353Sdim MCE.emitWordLE( 298234353Sdim (0x22 << 26) | (base << 21) | (dst << 16) | ((offset+3) & 0xffff)); 299234353Sdim return 2; 300234353Sdim } else { 301234353Sdim // lwr at, offset(base) 302234353Sdim // lwl at, offset+3(base) 303234353Sdim // addu dst, at, $zero 304234353Sdim MCE.emitWordLE( 305234353Sdim (0x26 << 26) | (base << 21) | (at << 16) | (offset & 0xffff)); 306234353Sdim MCE.emitWordLE( 307234353Sdim (0x22 << 26) | (base << 21) | (at << 16) | ((offset+3) & 0xffff)); 308234353Sdim MCE.emitWordLE( 309234353Sdim (0x0 << 26) | (at << 21) | (0x0 << 16) | (dst << 11) | (0x0 << 6) | 0x21); 310234353Sdim return 3; 311234353Sdim } 312234353Sdim} 313234353Sdim 314234353Sdimint MipsCodeEmitter::emitUSH(const MachineInstr &MI) { 315234353Sdim unsigned src = getMachineOpValue(MI, MI.getOperand(0)); 316234353Sdim unsigned base = getMachineOpValue(MI, MI.getOperand(1)); 317234353Sdim unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); 318234353Sdim unsigned at = 1; 319234353Sdim // sb src, offset(base) 320234353Sdim // srl at,src,8 321234353Sdim // sb at, offset+1(base) 322234353Sdim MCE.emitWordLE( 323234353Sdim (0x28 << 26) | (base << 21) | (src << 16) | (offset & 0xffff)); 324234353Sdim MCE.emitWordLE( 325234353Sdim (0x0 << 26) | (0x0 << 21) | (src << 16) | (at << 11) | (0x8 << 6) | 0x2); 326234353Sdim MCE.emitWordLE( 327234353Sdim (0x28 << 26) | (base << 21) | (at << 16) | ((offset+1) & 0xffff)); 328234353Sdim return 3; 329234353Sdim} 330234353Sdim 331234353Sdimint MipsCodeEmitter::emitULH(const MachineInstr &MI) { 332234353Sdim unsigned dst = getMachineOpValue(MI, MI.getOperand(0)); 333234353Sdim unsigned base = getMachineOpValue(MI, MI.getOperand(1)); 334234353Sdim unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); 335234353Sdim unsigned at = 1; 336234353Sdim // lbu at, offset(base) 337234353Sdim // lb dst, offset+1(base) 338234353Sdim // sll dst,dst,8 339234353Sdim // or dst,dst,at 340234353Sdim MCE.emitWordLE( 341234353Sdim (0x24 << 26) | (base << 21) | (at << 16) | (offset & 0xffff)); 342234353Sdim MCE.emitWordLE( 343234353Sdim (0x20 << 26) | (base << 21) | (dst << 16) | ((offset+1) & 0xffff)); 344234353Sdim MCE.emitWordLE( 345234353Sdim (0x0 << 26) | (0x0 << 21) | (dst << 16) | (dst << 11) | (0x8 << 6) | 0x0); 346234353Sdim MCE.emitWordLE( 347234353Sdim (0x0 << 26) | (dst << 21) | (at << 16) | (dst << 11) | (0x0 << 6) | 0x25); 348234353Sdim return 4; 349234353Sdim} 350234353Sdim 351234353Sdimint MipsCodeEmitter::emitULHu(const MachineInstr &MI) { 352234353Sdim unsigned dst = getMachineOpValue(MI, MI.getOperand(0)); 353234353Sdim unsigned base = getMachineOpValue(MI, MI.getOperand(1)); 354234353Sdim unsigned offset = getMachineOpValue(MI, MI.getOperand(2)); 355234353Sdim unsigned at = 1; 356234353Sdim // lbu at, offset(base) 357234353Sdim // lbu dst, offset+1(base) 358234353Sdim // sll dst,dst,8 359234353Sdim // or dst,dst,at 360234353Sdim MCE.emitWordLE( 361234353Sdim (0x24 << 26) | (base << 21) | (at << 16) | (offset & 0xffff)); 362234353Sdim MCE.emitWordLE( 363234353Sdim (0x24 << 26) | (base << 21) | (dst << 16) | ((offset+1) & 0xffff)); 364234353Sdim MCE.emitWordLE( 365234353Sdim (0x0 << 26) | (0x0 << 21) | (dst << 16) | (dst << 11) | (0x8 << 6) | 0x0); 366234353Sdim MCE.emitWordLE( 367234353Sdim (0x0 << 26) | (dst << 21) | (at << 16) | (dst << 11) | (0x0 << 6) | 0x25); 368234353Sdim return 4; 369234353Sdim} 370234353Sdim 371226584Sdimvoid MipsCodeEmitter::emitInstruction(const MachineInstr &MI) { 372226584Sdim DEBUG(errs() << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI); 373226584Sdim 374226584Sdim MCE.processDebugLoc(MI.getDebugLoc(), true); 375226584Sdim 376226584Sdim // Skip pseudo instructions. 377226584Sdim if ((MI.getDesc().TSFlags & MipsII::FormMask) == MipsII::Pseudo) 378226584Sdim return; 379226584Sdim 380243830Sdim emitWordLE(getBinaryCodeForInstr(MI)); 381243830Sdim ++NumEmitted; // Keep track of the # of mi's emitted 382226584Sdim 383226584Sdim MCE.processDebugLoc(MI.getDebugLoc(), false); 384226584Sdim} 385226584Sdim 386226584Sdimvoid MipsCodeEmitter::emitWordLE(unsigned Word) { 387226584Sdim DEBUG(errs() << " 0x"; 388226584Sdim errs().write_hex(Word) << "\n"); 389226584Sdim MCE.emitWordLE(Word); 390226584Sdim} 391226584Sdim 392226584Sdim/// createMipsJITCodeEmitterPass - Return a pass that emits the collected Mips 393226584Sdim/// code to the specified MCE object. 394226584SdimFunctionPass *llvm::createMipsJITCodeEmitterPass(MipsTargetMachine &TM, 395234353Sdim JITCodeEmitter &JCE) { 396226584Sdim return new MipsCodeEmitter(TM, JCE); 397226584Sdim} 398226584Sdim 399228379Sdim#include "MipsGenCodeEmitter.inc" 400