mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	Mips MC object code emission improvements:
"With this patch we can now generate runnable Mips code through LLVM direct object emission. We have run numerous simple programs, both C and C++ and with -O0 and -O3 from the output. The code is not production ready, but quite useful for experimentation." Patch and message by Jack Carter git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@144414 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		| @@ -1,5 +1,21 @@ | ||||
| //===-- MipsASMBackend.cpp -  ---------===// | ||||
| // | ||||
| //                     The LLVM Compiler Infrastructure | ||||
| // | ||||
| // This file is distributed under the University of Illinois Open Source | ||||
| // License. See LICENSE.TXT for details. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
| // | ||||
| // This file implements the MipsAsmBackend and MipsELFObjectWriter classes. | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
| // | ||||
|  | ||||
| #include "MipsFixupKinds.h" | ||||
| #include "MCTargetDesc/MipsMCTargetDesc.h" | ||||
| #include "llvm/ADT/Twine.h" | ||||
| #include "llvm/MC/MCAsmBackend.h" | ||||
| #include "llvm/MC/MCAssembler.h" | ||||
| #include "llvm/MC/MCDirectives.h" | ||||
| #include "llvm/MC/MCELFObjectWriter.h" | ||||
| @@ -8,7 +24,6 @@ | ||||
| #include "llvm/MC/MCObjectWriter.h" | ||||
| #include "llvm/MC/MCSectionELF.h" | ||||
| #include "llvm/MC/MCSectionMachO.h" | ||||
| #include "llvm/MC/MCAsmBackend.h" | ||||
| #include "llvm/MC/MCSubtargetInfo.h" | ||||
| #include "llvm/Object/MachOFormat.h" | ||||
| #include "llvm/Support/ELF.h" | ||||
| @@ -16,7 +31,50 @@ | ||||
| #include "llvm/Support/raw_ostream.h" | ||||
| using namespace llvm; | ||||
|  | ||||
| static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { | ||||
|  | ||||
|   // Add/subtract and shift | ||||
|   switch (Kind) { | ||||
|   default: | ||||
|     break; | ||||
|   case Mips::fixup_Mips_PC16: | ||||
|     // So far we are only using this type for branches. | ||||
|     // For branches we start 1 instruction after the branch | ||||
|     // so the displacement will be one instruction size less. | ||||
|     Value -= 4; | ||||
|     // The displacement is then divided by 4 to give us an 18 bit | ||||
|     // address range. | ||||
|     Value >>= 2; | ||||
|     break; | ||||
|   case Mips::fixup_Mips_26: | ||||
|     // So far we are only using this type for jumps. | ||||
|     // The displacement is then divided by 4 to give us an 28 bit | ||||
|     // address range. | ||||
|     Value >>= 2; | ||||
|     break; | ||||
|   } | ||||
|  | ||||
|   // Mask off value for placement as an operand | ||||
|   switch (Kind) { | ||||
|   default: | ||||
|     break; | ||||
|   case FK_Data_4: | ||||
|     Value &= 0xffffffff; | ||||
|     break; | ||||
|   case Mips::fixup_Mips_26: | ||||
|     Value &= 0x03ffffff; | ||||
|     break; | ||||
|   case Mips::fixup_Mips_LO16: | ||||
|   case Mips::fixup_Mips_PC16: | ||||
|     Value &= 0x0000ffff; | ||||
|     break; | ||||
|   } | ||||
|  | ||||
|   return Value; | ||||
| } | ||||
|  | ||||
| namespace { | ||||
|  | ||||
| class MipsELFObjectWriter : public MCELFObjectTargetWriter { | ||||
| public: | ||||
|   MipsELFObjectWriter(bool is64Bit, Triple::OSType OSType, uint16_t EMachine, | ||||
| @@ -27,18 +85,75 @@ public: | ||||
|  | ||||
| class MipsAsmBackend : public MCAsmBackend { | ||||
| public: | ||||
|   MipsAsmBackend(const Target &T) | ||||
|     : MCAsmBackend() {} | ||||
|  | ||||
|   unsigned getNumFixupKinds() const { | ||||
|     return 1;   //tbd | ||||
|   } | ||||
|   MipsAsmBackend(const Target &T) : MCAsmBackend() {} | ||||
|  | ||||
|   /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided | ||||
|   /// data fragment, at the offset specified by the fixup and following the | ||||
|   /// fixup kind as appropriate. | ||||
|   void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, | ||||
|                   uint64_t Value) const { | ||||
|     unsigned Kind = (unsigned)Fixup.getKind(); | ||||
|     Value = adjustFixupValue(Kind, Value); | ||||
|  | ||||
|     if (!Value) | ||||
|       return;           // Doesn't change encoding. | ||||
|  | ||||
|     unsigned Offset = Fixup.getOffset(); | ||||
|     switch (Kind) { | ||||
|     default: | ||||
|       llvm_unreachable("Unknown fixup kind!"); | ||||
|     case Mips::fixup_Mips_GOT16: // This will be fixed up at link time | ||||
|      break; | ||||
|     case FK_Data_4: | ||||
|     case Mips::fixup_Mips_26: | ||||
|     case Mips::fixup_Mips_LO16: | ||||
|     case Mips::fixup_Mips_PC16: | ||||
|       // For each byte of the fragment that the fixup touches, mask i | ||||
|       // the fixup value. The Value has been "split up" into the appr | ||||
|       // bitfields above. | ||||
|       for (unsigned i = 0; i != 4; ++i) // FIXME - Need to support 2 and 8 bytes | ||||
|         Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   unsigned getNumFixupKinds() const { return Mips::NumTargetFixupKinds; } | ||||
|  | ||||
|   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { | ||||
|     const static MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] = { | ||||
|       // This table *must* be in the order that the fixup_* kinds a | ||||
|       // MipsFixupKinds.h. | ||||
|       // | ||||
|       // name                    offset  bits  flags | ||||
|       { "fixup_Mips_NONE",         0,      0,   0 }, | ||||
|       { "fixup_Mips_16",           0,     16,   0 }, | ||||
|       { "fixup_Mips_32",           0,     32,   0 }, | ||||
|       { "fixup_Mips_REL32",        0,     32,   0 }, | ||||
|       { "fixup_Mips_26",           0,     26,   0 }, | ||||
|       { "fixup_Mips_HI16",         0,     16,   0 }, | ||||
|       { "fixup_Mips_LO16",         0,     16,   0 }, | ||||
|       { "fixup_Mips_GPREL16",      0,     16,   0 }, | ||||
|       { "fixup_Mips_LITERAL",      0,     16,   0 }, | ||||
|       { "fixup_Mips_GOT16",        0,     16,   0 }, | ||||
|       { "fixup_Mips_PC16",         0,     16,  MCFixupKindInfo::FKF_IsPCRel }, | ||||
|       { "fixup_Mips_CALL16",       0,     16,   0 }, | ||||
|       { "fixup_Mips_GPREL32",      0,     32,   0 }, | ||||
|       { "fixup_Mips_SHIFT5",       6,      5,   0 }, | ||||
|       { "fixup_Mips_SHIFT6",       6,      5,   0 }, | ||||
|       { "fixup_Mips_64",           0,     64,   0 }, | ||||
|       { "fixup_Mips_TLSGD",        0,     16,   0 }, | ||||
|       { "fixup_Mips_GOTTPREL",     0,     16,   0 }, | ||||
|       { "fixup_Mips_TPREL_HI",     0,     16,   0 }, | ||||
|       { "fixup_Mips_TPREL_LO",     0,     16,   0 }, | ||||
|       { "fixup_Mips_Branch_PCRel", 0,     16,  MCFixupKindInfo::FKF_IsPCRel } | ||||
|     }; | ||||
|  | ||||
|     if (Kind < FirstTargetFixupKind) | ||||
|       return MCAsmBackend::getFixupKindInfo(Kind); | ||||
|  | ||||
|     assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && | ||||
|            "Invalid kind!"); | ||||
|     return Infos[Kind - FirstTargetFixupKind]; | ||||
|   } | ||||
|  | ||||
|   /// @name Target Relaxation Interfaces | ||||
| @@ -52,24 +167,24 @@ public: | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   /// RelaxInstruction - Relax the instruction in the given fragment to the next | ||||
|   /// wider instruction. | ||||
|   /// RelaxInstruction - Relax the instruction in the given fragment | ||||
|   /// to the next wider instruction. | ||||
|   /// | ||||
|   /// \param Inst - The instruction to relax, which may be the same as the | ||||
|   /// output. | ||||
|   /// \param Inst - The instruction to relax, which may be the same | ||||
|   /// as the output. | ||||
|   /// \parm Res [output] - On return, the relaxed instruction. | ||||
|   void RelaxInstruction(const MCInst &Inst, MCInst &Res) const { | ||||
|   } | ||||
|    | ||||
|   /// @} | ||||
|  | ||||
|   /// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given | ||||
|   /// output. If the target cannot generate such a sequence, it should return an | ||||
|   /// error. | ||||
|   /// WriteNopData - Write an (optimal) nop sequence of Count bytes | ||||
|   /// to the given output. If the target cannot generate such a sequence, | ||||
|   /// it should return an error. | ||||
|   /// | ||||
|   /// \return - True on success. | ||||
|   bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const { | ||||
|     return false; | ||||
|     return true; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -106,7 +221,7 @@ public: | ||||
|     return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false); | ||||
|   } | ||||
| }; | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, StringRef TT) { | ||||
|   Triple TheTriple(TT); | ||||
|   | ||||
| @@ -19,6 +19,88 @@ | ||||
| #include "llvm/Support/ErrorHandling.h" | ||||
|  | ||||
| namespace llvm { | ||||
|  | ||||
| /// MipsII - This namespace holds all of the target specific flags that | ||||
| /// instruction info tracks. | ||||
| /// | ||||
| namespace MipsII { | ||||
|   /// Target Operand Flag enum. | ||||
|   enum TOF { | ||||
|     //===------------------------------------------------------------------===// | ||||
|     // Mips Specific MachineOperand flags. | ||||
|  | ||||
|     MO_NO_FLAG, | ||||
|  | ||||
|     /// MO_GOT - Represents the offset into the global offset table at which | ||||
|     /// the address the relocation entry symbol resides during execution. | ||||
|     MO_GOT, | ||||
|  | ||||
|     /// MO_GOT_CALL - Represents the offset into the global offset table at | ||||
|     /// which the address of a call site relocation entry symbol resides | ||||
|     /// during execution. This is different from the above since this flag | ||||
|     /// can only be present in call instructions. | ||||
|     MO_GOT_CALL, | ||||
|  | ||||
|     /// MO_GPREL - Represents the offset from the current gp value to be used | ||||
|     /// for the relocatable object file being produced. | ||||
|     MO_GPREL, | ||||
|  | ||||
|     /// MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol | ||||
|     /// address. | ||||
|     MO_ABS_HI, | ||||
|     MO_ABS_LO, | ||||
|  | ||||
|     /// MO_TLSGD - Represents the offset into the global offset table at which | ||||
|     // the module ID and TSL block offset reside during execution (General | ||||
|     // Dynamic TLS). | ||||
|     MO_TLSGD, | ||||
|  | ||||
|     /// MO_GOTTPREL - Represents the offset from the thread pointer (Initial | ||||
|     // Exec TLS). | ||||
|     MO_GOTTPREL, | ||||
|  | ||||
|     /// MO_TPREL_HI/LO - Represents the hi and low part of the offset from | ||||
|     // the thread pointer (Local Exec TLS). | ||||
|     MO_TPREL_HI, | ||||
|     MO_TPREL_LO, | ||||
|  | ||||
|     // N32/64 Flags. | ||||
|     MO_GPOFF_HI, | ||||
|     MO_GPOFF_LO, | ||||
|     MO_GOT_DISP, | ||||
|     MO_GOT_PAGE, | ||||
|     MO_GOT_OFST | ||||
|   }; | ||||
|  | ||||
|   enum { | ||||
|     //===------------------------------------------------------------------===// | ||||
|     // Instruction encodings.  These are the standard/most common forms for | ||||
|     // Mips instructions. | ||||
|     // | ||||
|  | ||||
|     // Pseudo - This represents an instruction that is a pseudo instruction | ||||
|     // or one that has not been implemented yet.  It is illegal to code generate | ||||
|     // it, but tolerated for intermediate implementation stages. | ||||
|     Pseudo   = 0, | ||||
|  | ||||
|     /// FrmR - This form is for instructions of the format R. | ||||
|     FrmR  = 1, | ||||
|     /// FrmI - This form is for instructions of the format I. | ||||
|     FrmI  = 2, | ||||
|     /// FrmJ - This form is for instructions of the format J. | ||||
|     FrmJ  = 3, | ||||
|     /// FrmFR - This form is for instructions of the format FR. | ||||
|     FrmFR = 4, | ||||
|     /// FrmFI - This form is for instructions of the format FI. | ||||
|     FrmFI = 5, | ||||
|     /// FrmOther - This form is for instructions that have no specific format. | ||||
|     FrmOther = 6, | ||||
|  | ||||
|     FormMask = 15 | ||||
|   }; | ||||
| } | ||||
|  | ||||
|  | ||||
| /// getMipsRegisterNumbering - Given the enum value for some register, | ||||
| /// return the number that it corresponds to. | ||||
| inline static unsigned getMipsRegisterNumbering(unsigned RegEnum) | ||||
|   | ||||
| @@ -12,16 +12,18 @@ | ||||
| //===----------------------------------------------------------------------===// | ||||
| // | ||||
| #define DEBUG_TYPE "mccodeemitter" | ||||
| #include "MCTargetDesc/MipsBaseInfo.h" | ||||
| #include "MCTargetDesc/MipsFixupKinds.h" | ||||
| #include "MCTargetDesc/MipsMCTargetDesc.h" | ||||
| #include "llvm/ADT/APFloat.h" | ||||
| #include "llvm/ADT/Statistic.h" | ||||
| #include "llvm/MC/MCCodeEmitter.h" | ||||
| #include "llvm/MC/MCExpr.h" | ||||
| #include "llvm/MC/MCInst.h" | ||||
| #include "llvm/MC/MCInstrInfo.h" | ||||
| #include "llvm/MC/MCRegisterInfo.h" | ||||
| #include "llvm/MC/MCSubtargetInfo.h" | ||||
| #include "llvm/ADT/APFloat.h" | ||||
| #include "llvm/ADT/Statistic.h" | ||||
| #include "llvm/Support/raw_ostream.h" | ||||
| #include "MCTargetDesc/MipsMCTargetDesc.h" | ||||
|  | ||||
| using namespace llvm; | ||||
|  | ||||
| @@ -31,22 +33,217 @@ class MipsMCCodeEmitter : public MCCodeEmitter { | ||||
|   void operator=(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT | ||||
|   const MCInstrInfo &MCII; | ||||
|   const MCSubtargetInfo &STI; | ||||
|   MCContext &Ctx; | ||||
|  | ||||
| public: | ||||
|   MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, | ||||
|                     MCContext &ctx) | ||||
|     : MCII(mcii), STI(sti) {} | ||||
|                     MCContext &ctx) : MCII(mcii), STI(sti) , Ctx(ctx) {} | ||||
|  | ||||
|   ~MipsMCCodeEmitter() {} | ||||
|  | ||||
|   void EncodeInstruction(const MCInst &MI, raw_ostream &OS, | ||||
|                          SmallVectorImpl<MCFixup> &Fixups) const { | ||||
|   void EmitByte(unsigned char C, raw_ostream &OS) const { | ||||
|     OS << (char)C; | ||||
|   } | ||||
|  | ||||
|   void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const { | ||||
|     // Output the instruction encoding in little endian byte order. | ||||
|     for (unsigned i = 0; i != Size; ++i) { | ||||
|       EmitByte(Val & 255, OS); | ||||
|       Val >>= 8; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void EncodeInstruction(const MCInst &MI, raw_ostream &OS, | ||||
|                          SmallVectorImpl<MCFixup> &Fixups) const; | ||||
|  | ||||
|   // getBinaryCodeForInstr - TableGen'erated function for getting the | ||||
|   // binary encoding for an instruction. | ||||
|   unsigned getBinaryCodeForInstr(const MCInst &MI, | ||||
|                                  SmallVectorImpl<MCFixup> &Fixups) const; | ||||
|  | ||||
|   // getBranchJumpOpValue - Return binary encoding of the jump | ||||
|   // target operand. If the machine operand requires relocation, | ||||
|   // record the relocation and return zero. | ||||
|    unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, | ||||
|                                  SmallVectorImpl<MCFixup> &Fixups) const; | ||||
|  | ||||
|    // getBranchTargetOpValue - Return binary encoding of the branch | ||||
|    // target operand. If the machine operand requires relocation, | ||||
|    // record the relocation and return zero. | ||||
|   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, | ||||
|                                   SmallVectorImpl<MCFixup> &Fixups) const; | ||||
|  | ||||
|    // getMachineOpValue - Return binary encoding of operand. If the machin | ||||
|    // operand requires relocation, record the relocation and return zero. | ||||
|   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, | ||||
|                              SmallVectorImpl<MCFixup> &Fixups) const; | ||||
|  | ||||
|   unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, | ||||
|                           SmallVectorImpl<MCFixup> &Fixups) const; | ||||
|   unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo, | ||||
|                               SmallVectorImpl<MCFixup> &Fixups) const; | ||||
|   unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo, | ||||
|                               SmallVectorImpl<MCFixup> &Fixups) const; | ||||
|  | ||||
| }; // class MipsMCCodeEmitter | ||||
| }  // namespace | ||||
|  | ||||
| MCCodeEmitter *llvm::createMipsMCCodeEmitter(const MCInstrInfo &MCII, | ||||
|                                              const MCSubtargetInfo &STI, | ||||
|                                              MCContext &Ctx) { | ||||
|                                              MCContext &Ctx) | ||||
| { | ||||
|   return new MipsMCCodeEmitter(MCII, STI, Ctx); | ||||
| } | ||||
|  | ||||
| /// EncodeInstruction - Emit the instruction. | ||||
| /// Size the instruction (currently only 4 bytes | ||||
| void MipsMCCodeEmitter:: | ||||
| EncodeInstruction(const MCInst &MI, raw_ostream &OS, | ||||
|                   SmallVectorImpl<MCFixup> &Fixups) const | ||||
| { | ||||
|   uint32_t Binary = getBinaryCodeForInstr(MI, Fixups); | ||||
|  | ||||
|   // Check for unimplemented opcodes. | ||||
|   // Unfortunately in MIPS both NOT and SLL will come in with Binary == 0 | ||||
|   // so we have to special check for them. | ||||
|   unsigned Opcode = MI.getOpcode(); | ||||
|   if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary) | ||||
|     llvm_unreachable("unimplemented opcode in EncodeInstruction()"); | ||||
|  | ||||
|   const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); | ||||
|   uint64_t TSFlags = Desc.TSFlags; | ||||
|  | ||||
|   // Pseudo instructions don't get encoded and shouldn't be here | ||||
|   // in the first place! | ||||
|   if ((TSFlags & MipsII::FormMask) == MipsII::Pseudo) | ||||
|     llvm_unreachable("Pseudo opcode found in EncodeInstruction()"); | ||||
|  | ||||
|   // For now all instructions are 4 bytes | ||||
|   int Size = 4; // FIXME: Have Desc.getSize() return the correct value! | ||||
|  | ||||
|   EmitInstruction(Binary, Size, OS); | ||||
| } | ||||
|  | ||||
| /// getBranchTargetOpValue - Return binary encoding of the branch | ||||
| /// target operand. If the machine operand requires relocation, | ||||
| /// record the relocation and return zero. | ||||
| unsigned MipsMCCodeEmitter:: | ||||
| getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, | ||||
|                        SmallVectorImpl<MCFixup> &Fixups) const { | ||||
|  | ||||
|   const MCOperand &MO = MI.getOperand(OpNo); | ||||
|   assert(MO.isExpr() && "getBranchTargetOpValue expects only expressions"); | ||||
|  | ||||
|   const MCExpr *Expr = MO.getExpr(); | ||||
|   Fixups.push_back(MCFixup::Create(0, Expr, | ||||
|                                    MCFixupKind(Mips::fixup_Mips_PC16))); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| /// getJumpTargetOpValue - Return binary encoding of the jump | ||||
| /// target operand. If the machine operand requires relocation, | ||||
| /// record the relocation and return zero. | ||||
| unsigned MipsMCCodeEmitter:: | ||||
| getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, | ||||
|                      SmallVectorImpl<MCFixup> &Fixups) const { | ||||
|  | ||||
|   const MCOperand &MO = MI.getOperand(OpNo); | ||||
|   assert(MO.isExpr() && "getJumpTargetOpValue expects only expressions"); | ||||
|  | ||||
|   const MCExpr *Expr = MO.getExpr(); | ||||
|   Fixups.push_back(MCFixup::Create(0, Expr, | ||||
|                                    MCFixupKind(Mips::fixup_Mips_26))); | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| /// getMachineOpValue - Return binary encoding of operand. If the machine | ||||
| /// operand requires relocation, record the relocation and return zero. | ||||
| unsigned MipsMCCodeEmitter:: | ||||
| getMachineOpValue(const MCInst &MI, const MCOperand &MO, | ||||
|                   SmallVectorImpl<MCFixup> &Fixups) const { | ||||
|   if (MO.isReg()) { | ||||
|     unsigned Reg = MO.getReg(); | ||||
|     unsigned RegNo = getMipsRegisterNumbering(Reg); | ||||
|     return RegNo; | ||||
|   } else if (MO.isImm()) { | ||||
|     return static_cast<unsigned>(MO.getImm()); | ||||
|   } else if (MO.isFPImm()) { | ||||
|     return static_cast<unsigned>(APFloat(MO.getFPImm()) | ||||
|         .bitcastToAPInt().getHiBits(32).getLimitedValue()); | ||||
|   } else if (MO.isExpr()) { | ||||
|     const MCExpr *Expr = MO.getExpr(); | ||||
|     MCExpr::ExprKind Kind = Expr->getKind(); | ||||
|     if (Kind == MCExpr::SymbolRef) { | ||||
|       Mips::Fixups FixupKind = Mips::fixup_Mips_NONE; | ||||
|       MCSymbolRefExpr::VariantKind SymRefKind = | ||||
|           cast<MCSymbolRefExpr>(Expr)->getKind(); | ||||
|       switch(SymRefKind) { | ||||
|       case MCSymbolRefExpr::VK_Mips_GPREL: | ||||
|         FixupKind = Mips::fixup_Mips_GPREL16; | ||||
|         break; | ||||
|       case MCSymbolRefExpr::VK_Mips_GOT_CALL: | ||||
|         FixupKind = Mips::fixup_Mips_CALL16; | ||||
|         break; | ||||
|       case MCSymbolRefExpr::VK_Mips_GOT: | ||||
|         FixupKind = Mips::fixup_Mips_GOT16; | ||||
|         break; | ||||
|       case MCSymbolRefExpr::VK_Mips_ABS_HI: | ||||
|         FixupKind = Mips::fixup_Mips_HI16; | ||||
|         break; | ||||
|       case MCSymbolRefExpr::VK_Mips_ABS_LO: | ||||
|         FixupKind = Mips::fixup_Mips_LO16; | ||||
|         break; | ||||
|       case MCSymbolRefExpr::VK_Mips_TLSGD: | ||||
|         FixupKind = Mips::fixup_Mips_TLSGD; | ||||
|         break; | ||||
|       case MCSymbolRefExpr::VK_Mips_GOTTPREL: | ||||
|         FixupKind = Mips::fixup_Mips_GOTTPREL; | ||||
|         break; | ||||
|       case MCSymbolRefExpr::VK_Mips_TPREL_HI: | ||||
|         FixupKind = Mips::fixup_Mips_TPREL_HI; | ||||
|         break; | ||||
|       case MCSymbolRefExpr::VK_Mips_TPREL_LO: | ||||
|         FixupKind = Mips::fixup_Mips_TPREL_LO; | ||||
|         break; | ||||
|       default: | ||||
|         return 0; | ||||
|       } // switch | ||||
|       Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind))); | ||||
|     } // if SymbolRef | ||||
|     // All of the information is in the fixup. | ||||
|     return 0; | ||||
|   } | ||||
|   llvm_unreachable("Unable to encode MCOperand!"); | ||||
|   // Not reached | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| /// getMemEncoding - Return binary encoding of memory related operand. | ||||
| /// If the offset operand requires relocation, record the relocation. | ||||
| unsigned | ||||
| MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, | ||||
|                                   SmallVectorImpl<MCFixup> &Fixups) 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),Fixups) << 16; | ||||
|   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups); | ||||
|  | ||||
|   return (OffBits & 0xFFFF) | RegBits; | ||||
| } | ||||
|  | ||||
| unsigned | ||||
| MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo, | ||||
|                                       SmallVectorImpl<MCFixup> &Fixups) const { | ||||
|   // FIXME: implement | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| unsigned | ||||
| MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, | ||||
|                                       SmallVectorImpl<MCFixup> &Fixups) const { | ||||
|   // FIXME: implement | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| #include "MipsGenMCCodeEmitter.inc" | ||||
|  | ||||
|   | ||||
| @@ -11,8 +11,8 @@ | ||||
| // | ||||
| //===----------------------------------------------------------------------===// | ||||
|  | ||||
| #include "MipsMCTargetDesc.h" | ||||
| #include "MipsMCAsmInfo.h" | ||||
| #include "MipsMCTargetDesc.h" | ||||
| #include "InstPrinter/MipsInstPrinter.h" | ||||
| #include "llvm/MC/MachineLocation.h" | ||||
| #include "llvm/MC/MCCodeGenInfo.h" | ||||
| @@ -140,6 +140,9 @@ extern "C" void LLVMInitializeMipsTargetMC() { | ||||
|   TargetRegistry::RegisterMCAsmBackend(TheMips64Target, createMipsAsmBackend); | ||||
|   TargetRegistry::RegisterMCAsmBackend(TheMips64elTarget, createMipsAsmBackend); | ||||
|  | ||||
|   TargetRegistry::RegisterMCCodeEmitter(TheMipsTarget, createMipsMCCodeEmitter); | ||||
|   TargetRegistry::RegisterMCCodeEmitter(TheMipselTarget, createMipsMCCodeEmitter); | ||||
|  | ||||
|   // Register the MC subtarget info. | ||||
|   TargetRegistry::RegisterMCSubtargetInfo(TheMipsTarget, | ||||
|                                           createMipsMCSubtargetInfo); | ||||
|   | ||||
| @@ -16,12 +16,14 @@ | ||||
|  | ||||
| namespace llvm { | ||||
| class MCAsmBackend; | ||||
| class MCInstrInfo; | ||||
| class MCCodeEmitter; | ||||
| class MCContext; | ||||
| class MCInstrInfo; | ||||
| class MCObjectWriter; | ||||
| class MCSubtargetInfo; | ||||
| class StringRef; | ||||
| class Target; | ||||
| class raw_ostream; | ||||
|  | ||||
| extern Target TheMipsTarget; | ||||
| extern Target TheMipselTarget; | ||||
| @@ -33,6 +35,7 @@ MCCodeEmitter *createMipsMCCodeEmitter(const MCInstrInfo &MCII, | ||||
|                                        MCContext &Ctx); | ||||
|  | ||||
| MCAsmBackend *createMipsAsmBackend(const Target &T, StringRef TT); | ||||
|  | ||||
| } // End llvm namespace | ||||
|  | ||||
| // Defines symbolic names for Mips registers.  This defines a mapping from | ||||
|   | ||||
| @@ -15,7 +15,7 @@ TARGET = Mips | ||||
| BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrInfo.inc \ | ||||
|                 MipsGenAsmWriter.inc MipsGenCodeEmitter.inc \ | ||||
|                 MipsGenDAGISel.inc MipsGenCallingConv.inc \ | ||||
|                 MipsGenSubtargetInfo.inc | ||||
|                 MipsGenSubtargetInfo.inc MipsGenMCCodeEmitter.inc | ||||
|  | ||||
| DIRS = InstPrinter TargetInfo MCTargetDesc | ||||
|  | ||||
|   | ||||
| @@ -20,6 +20,7 @@ | ||||
| #include "MipsMCInstLower.h" | ||||
| #include "MipsMCSymbolRefExpr.h" | ||||
| #include "InstPrinter/MipsInstPrinter.h" | ||||
| #include "MCTargetDesc/MipsBaseInfo.h" | ||||
| #include "llvm/ADT/SmallString.h" | ||||
| #include "llvm/ADT/StringExtras.h" | ||||
| #include "llvm/ADT/Twine.h" | ||||
|   | ||||
| @@ -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); | ||||
| @@ -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,6 +105,9 @@ 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; | ||||
| @@ -165,23 +168,34 @@ unsigned MipsCodeEmitter::getRelocation(const MachineInstr &MI, | ||||
|   return Mips::reloc_mips_lo; | ||||
| } | ||||
|  | ||||
| unsigned MipsCodeEmitter::getJumpTargetOpValue(const MachineInstr &MI, | ||||
|                                                unsigned OpNo) const { | ||||
|   // FIXME: implement | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| unsigned MipsCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI, | ||||
|                                                  unsigned OpNo) const { | ||||
|   // FIXME: implement | ||||
|   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; | ||||
| @@ -190,7 +204,7 @@ 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()); | ||||
|   else if (MO.isImm()) | ||||
| @@ -217,9 +231,10 @@ 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, | ||||
| @@ -248,7 +263,7 @@ 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)); | ||||
| } | ||||
| @@ -395,7 +410,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); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| #include "MipsFrameLowering.h" | ||||
| #include "MipsInstrInfo.h" | ||||
| #include "MipsMachineFunction.h" | ||||
| #include "MCTargetDesc/MipsBaseInfo.h" | ||||
| #include "llvm/Function.h" | ||||
| #include "llvm/CodeGen/MachineFrameInfo.h" | ||||
| #include "llvm/CodeGen/MachineFunction.h" | ||||
|   | ||||
| @@ -24,6 +24,7 @@ | ||||
| #include "llvm/Intrinsics.h" | ||||
| #include "llvm/CallingConv.h" | ||||
| #include "InstPrinter/MipsInstPrinter.h" | ||||
| #include "MCTargetDesc/MipsBaseInfo.h" | ||||
| #include "llvm/CodeGen/CallingConvLower.h" | ||||
| #include "llvm/CodeGen/MachineFrameInfo.h" | ||||
| #include "llvm/CodeGen/MachineFunction.h" | ||||
|   | ||||
| @@ -30,86 +30,6 @@ namespace Mips { | ||||
|   unsigned GetOppositeBranchOpc(unsigned Opc); | ||||
| } | ||||
|  | ||||
| /// MipsII - This namespace holds all of the target specific flags that | ||||
| /// instruction info tracks. | ||||
| /// | ||||
| namespace MipsII { | ||||
|   /// Target Operand Flag enum. | ||||
|   enum TOF { | ||||
|     //===------------------------------------------------------------------===// | ||||
|     // Mips Specific MachineOperand flags. | ||||
|  | ||||
|     MO_NO_FLAG, | ||||
|  | ||||
|     /// MO_GOT - Represents the offset into the global offset table at which | ||||
|     /// the address the relocation entry symbol resides during execution. | ||||
|     MO_GOT, | ||||
|  | ||||
|     /// MO_GOT_CALL - Represents the offset into the global offset table at | ||||
|     /// which the address of a call site relocation entry symbol resides | ||||
|     /// during execution. This is different from the above since this flag | ||||
|     /// can only be present in call instructions. | ||||
|     MO_GOT_CALL, | ||||
|  | ||||
|     /// MO_GPREL - Represents the offset from the current gp value to be used | ||||
|     /// for the relocatable object file being produced. | ||||
|     MO_GPREL, | ||||
|  | ||||
|     /// MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol | ||||
|     /// address. | ||||
|     MO_ABS_HI, | ||||
|     MO_ABS_LO, | ||||
|  | ||||
|     /// MO_TLSGD - Represents the offset into the global offset table at which | ||||
|     // the module ID and TSL block offset reside during execution (General | ||||
|     // Dynamic TLS). | ||||
|     MO_TLSGD, | ||||
|  | ||||
|     /// MO_GOTTPREL - Represents the offset from the thread pointer (Initial | ||||
|     // Exec TLS). | ||||
|     MO_GOTTPREL, | ||||
|  | ||||
|     /// MO_TPREL_HI/LO - Represents the hi and low part of the offset from | ||||
|     // the thread pointer (Local Exec TLS). | ||||
|     MO_TPREL_HI, | ||||
|     MO_TPREL_LO, | ||||
|  | ||||
|     // N32/64 Flags. | ||||
|     MO_GPOFF_HI, | ||||
|     MO_GPOFF_LO, | ||||
|     MO_GOT_DISP, | ||||
|     MO_GOT_PAGE, | ||||
|     MO_GOT_OFST | ||||
|   }; | ||||
|  | ||||
|   enum { | ||||
|     //===------------------------------------------------------------------===// | ||||
|     // Instruction encodings.  These are the standard/most common forms for | ||||
|     // Mips instructions. | ||||
|     // | ||||
|  | ||||
|     // Pseudo - This represents an instruction that is a pseudo instruction | ||||
|     // or one that has not been implemented yet.  It is illegal to code generate | ||||
|     // it, but tolerated for intermediate implementation stages. | ||||
|     Pseudo   = 0, | ||||
|  | ||||
|     /// FrmR - This form is for instructions of the format R. | ||||
|     FrmR  = 1, | ||||
|     /// FrmI - This form is for instructions of the format I. | ||||
|     FrmI  = 2, | ||||
|     /// FrmJ - This form is for instructions of the format J. | ||||
|     FrmJ  = 3, | ||||
|     /// FrmFR - This form is for instructions of the format FR. | ||||
|     FrmFR = 4, | ||||
|     /// FrmFI - This form is for instructions of the format FI. | ||||
|     FrmFI = 5, | ||||
|     /// FrmOther - This form is for instructions that have no specific format. | ||||
|     FrmOther = 6, | ||||
|  | ||||
|     FormMask = 15 | ||||
|   }; | ||||
| } | ||||
|  | ||||
| class MipsInstrInfo : public MipsGenInstrInfo { | ||||
|   MipsTargetMachine &TM; | ||||
|   bool IsN64; | ||||
|   | ||||
| @@ -138,7 +138,13 @@ def NotN64      : Predicate<"!Subtarget.isABI_N64()">; | ||||
| //===----------------------------------------------------------------------===// | ||||
|  | ||||
| // Instruction operand types | ||||
| def brtarget    : Operand<OtherVT>; | ||||
| def jmptarget   : Operand<OtherVT> { | ||||
|   let EncoderMethod = "getJumpTargetOpValue"; | ||||
| } | ||||
| def brtarget    : Operand<OtherVT> { | ||||
|   let EncoderMethod = "getBranchTargetOpValue"; | ||||
|   let OperandType = "OPERAND_PCREL"; | ||||
| } | ||||
| def calltarget  : Operand<i32>; | ||||
| def calltarget64: Operand<i64>; | ||||
| def simm16      : Operand<i32>; | ||||
| @@ -449,7 +455,7 @@ class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op, Operand Od, | ||||
| // Unconditional branch | ||||
| let isBranch=1, isTerminator=1, isBarrier=1, hasDelaySlot = 1 in | ||||
| class JumpFJ<bits<6> op, string instr_asm>: | ||||
|   FJ<op, (outs), (ins brtarget:$target), | ||||
|   FJ<op, (outs), (ins jmptarget:$target), | ||||
|      !strconcat(instr_asm, "\t$target"), [(br bb:$target)], IIBranch>; | ||||
|  | ||||
| let isBranch=1, isTerminator=1, isBarrier=1, rd=0, hasDelaySlot = 1 in | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include "MipsAsmPrinter.h" | ||||
| #include "MipsInstrInfo.h" | ||||
| #include "MipsMCInstLower.h" | ||||
| #include "MCTargetDesc/MipsBaseInfo.h" | ||||
| #include "llvm/CodeGen/MachineFunction.h" | ||||
| #include "llvm/CodeGen/MachineInstr.h" | ||||
| #include "llvm/CodeGen/MachineOperand.h" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user