LLVM API Documentation
00001 //===-- MBlazeAsmBackend.cpp - MBlaze Assembler Backend -------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "MCTargetDesc/MBlazeMCTargetDesc.h" 00011 #include "llvm/ADT/Twine.h" 00012 #include "llvm/MC/MCAsmBackend.h" 00013 #include "llvm/MC/MCAsmLayout.h" 00014 #include "llvm/MC/MCAssembler.h" 00015 #include "llvm/MC/MCELFObjectWriter.h" 00016 #include "llvm/MC/MCELFSymbolFlags.h" 00017 #include "llvm/MC/MCExpr.h" 00018 #include "llvm/MC/MCObjectWriter.h" 00019 #include "llvm/MC/MCSectionELF.h" 00020 #include "llvm/MC/MCSectionMachO.h" 00021 #include "llvm/MC/MCValue.h" 00022 #include "llvm/Support/ELF.h" 00023 #include "llvm/Support/ErrorHandling.h" 00024 #include "llvm/Support/TargetRegistry.h" 00025 #include "llvm/Support/raw_ostream.h" 00026 using namespace llvm; 00027 00028 static unsigned getFixupKindSize(unsigned Kind) { 00029 switch (Kind) { 00030 default: llvm_unreachable("invalid fixup kind!"); 00031 case FK_Data_1: return 1; 00032 case FK_PCRel_2: 00033 case FK_Data_2: return 2; 00034 case FK_PCRel_4: 00035 case FK_Data_4: return 4; 00036 case FK_Data_8: return 8; 00037 } 00038 } 00039 00040 00041 namespace { 00042 00043 class MBlazeAsmBackend : public MCAsmBackend { 00044 public: 00045 MBlazeAsmBackend(const Target &T) 00046 : MCAsmBackend() { 00047 } 00048 00049 unsigned getNumFixupKinds() const { 00050 return 2; 00051 } 00052 00053 bool mayNeedRelaxation(const MCInst &Inst) const; 00054 00055 bool fixupNeedsRelaxation(const MCFixup &Fixup, 00056 uint64_t Value, 00057 const MCRelaxableFragment *DF, 00058 const MCAsmLayout &Layout) const; 00059 00060 void relaxInstruction(const MCInst &Inst, MCInst &Res) const; 00061 00062 bool writeNopData(uint64_t Count, MCObjectWriter *OW) const; 00063 00064 unsigned getPointerSize() const { 00065 return 4; 00066 } 00067 }; 00068 00069 static unsigned getRelaxedOpcode(unsigned Op) { 00070 switch (Op) { 00071 default: return Op; 00072 case MBlaze::ADDIK: return MBlaze::ADDIK32; 00073 case MBlaze::ORI: return MBlaze::ORI32; 00074 case MBlaze::BRLID: return MBlaze::BRLID32; 00075 } 00076 } 00077 00078 bool MBlazeAsmBackend::mayNeedRelaxation(const MCInst &Inst) const { 00079 if (getRelaxedOpcode(Inst.getOpcode()) == Inst.getOpcode()) 00080 return false; 00081 00082 bool hasExprOrImm = false; 00083 for (unsigned i = 0; i < Inst.getNumOperands(); ++i) 00084 hasExprOrImm |= Inst.getOperand(i).isExpr(); 00085 00086 return hasExprOrImm; 00087 } 00088 00089 bool MBlazeAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, 00090 uint64_t Value, 00091 const MCRelaxableFragment *DF, 00092 const MCAsmLayout &Layout) const { 00093 // FIXME: Is this right? It's what the "generic" code was doing before, 00094 // but is X86 specific. Is it actually true for MBlaze also, or was it 00095 // just close enough to not be a big deal? 00096 // 00097 // Relax if the value is too big for a (signed) i8. 00098 return int64_t(Value) != int64_t(int8_t(Value)); 00099 } 00100 00101 void MBlazeAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const { 00102 Res = Inst; 00103 Res.setOpcode(getRelaxedOpcode(Inst.getOpcode())); 00104 } 00105 00106 bool MBlazeAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { 00107 if ((Count % 4) != 0) 00108 return false; 00109 00110 for (uint64_t i = 0; i < Count; i += 4) 00111 OW->Write32(0x00000000); 00112 00113 return true; 00114 } 00115 } // end anonymous namespace 00116 00117 namespace { 00118 class ELFMBlazeAsmBackend : public MBlazeAsmBackend { 00119 public: 00120 uint8_t OSABI; 00121 ELFMBlazeAsmBackend(const Target &T, uint8_t _OSABI) 00122 : MBlazeAsmBackend(T), OSABI(_OSABI) { } 00123 00124 void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 00125 uint64_t Value) const; 00126 00127 MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 00128 return createMBlazeELFObjectWriter(OS, OSABI); 00129 } 00130 }; 00131 00132 void ELFMBlazeAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, 00133 unsigned DataSize, uint64_t Value) const { 00134 unsigned Size = getFixupKindSize(Fixup.getKind()); 00135 00136 assert(Fixup.getOffset() + Size <= DataSize && 00137 "Invalid fixup offset!"); 00138 00139 char *data = Data + Fixup.getOffset(); 00140 switch (Size) { 00141 default: llvm_unreachable("Cannot fixup unknown value."); 00142 case 1: llvm_unreachable("Cannot fixup 1 byte value."); 00143 case 8: llvm_unreachable("Cannot fixup 8 byte value."); 00144 00145 case 4: 00146 *(data+7) = uint8_t(Value); 00147 *(data+6) = uint8_t(Value >> 8); 00148 *(data+3) = uint8_t(Value >> 16); 00149 *(data+2) = uint8_t(Value >> 24); 00150 break; 00151 00152 case 2: 00153 *(data+3) = uint8_t(Value >> 0); 00154 *(data+2) = uint8_t(Value >> 8); 00155 } 00156 } 00157 } // end anonymous namespace 00158 00159 MCAsmBackend *llvm::createMBlazeAsmBackend(const Target &T, StringRef TT, 00160 StringRef CPU) { 00161 Triple TheTriple(TT); 00162 00163 if (TheTriple.isOSDarwin()) 00164 assert(0 && "Mac not supported on MBlaze"); 00165 00166 if (TheTriple.isOSWindows()) 00167 assert(0 && "Windows not supported on MBlaze"); 00168 00169 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); 00170 return new ELFMBlazeAsmBackend(T, OSABI); 00171 }