diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 210 |
1 files changed, 189 insertions, 21 deletions
diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 9460731..66428bd 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -13,7 +13,6 @@ // #define DEBUG_TYPE "mccodeemitter" #include "MCTargetDesc/MipsBaseInfo.h" -#include "MCTargetDesc/MipsDirectObjLower.h" #include "MCTargetDesc/MipsFixupKinds.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/ADT/APFloat.h" @@ -40,11 +39,14 @@ class MipsMCCodeEmitter : public MCCodeEmitter { MCContext &Ctx; const MCSubtargetInfo &STI; bool IsLittleEndian; + bool IsMicroMips; public: MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, const MCSubtargetInfo &sti, bool IsLittle) : - MCII(mcii), Ctx(Ctx_), STI (sti), IsLittleEndian(IsLittle) {} + MCII(mcii), Ctx(Ctx_), STI (sti), IsLittleEndian(IsLittle) { + IsMicroMips = STI.getFeatureBits() & Mips::FeatureMicroMips; + } ~MipsMCCodeEmitter() {} @@ -54,9 +56,17 @@ public: 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) { - unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; - EmitByte((Val >> Shift) & 0xff, OS); + // Little-endian byte ordering: + // mips32r2: 4 | 3 | 2 | 1 + // microMIPS: 2 | 1 | 4 | 3 + if (IsLittleEndian && Size == 4 && IsMicroMips) { + EmitInstruction(Val>>16, 2, OS); + EmitInstruction(Val, 2, OS); + } else { + for (unsigned i = 0; i < Size; ++i) { + unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8; + EmitByte((Val >> Shift) & 0xff, OS); + } } } @@ -74,12 +84,24 @@ public: unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const; + // getBranchJumpOpValueMM - Return binary encoding of the microMIPS jump + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getJumpTargetOpValueMM(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; + // getBranchTargetOpValue - Return binary encoding of the microMIPS branch + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTargetOpValueMM(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, @@ -87,11 +109,17 @@ public: unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const; + unsigned getMemEncodingMMImm12(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; + // getLSAImmEncoding - Return binary encoding of LSA immediate. + unsigned getLSAImmEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const; + unsigned getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const; @@ -114,8 +142,74 @@ MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, return new MipsMCCodeEmitter(MCII, Ctx, STI, true); } + +// If the D<shift> instruction has a shift amount that is greater +// than 31 (checked in calling routine), lower it to a D<shift>32 instruction +static void LowerLargeShift(MCInst& Inst) { + + assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!"); + assert(Inst.getOperand(2).isImm()); + + int64_t Shift = Inst.getOperand(2).getImm(); + if (Shift <= 31) + return; // Do nothing + Shift -= 32; + + // saminus32 + Inst.getOperand(2).setImm(Shift); + + switch (Inst.getOpcode()) { + default: + // Calling function is not synchronized + llvm_unreachable("Unexpected shift instruction"); + case Mips::DSLL: + Inst.setOpcode(Mips::DSLL32); + return; + case Mips::DSRL: + Inst.setOpcode(Mips::DSRL32); + return; + case Mips::DSRA: + Inst.setOpcode(Mips::DSRA32); + return; + case Mips::DROTR: + Inst.setOpcode(Mips::DROTR32); + return; + } +} + +// Pick a DEXT or DINS instruction variant based on the pos and size operands +static void LowerDextDins(MCInst& InstIn) { + int Opcode = InstIn.getOpcode(); + + if (Opcode == Mips::DEXT) + assert(InstIn.getNumOperands() == 4 && + "Invalid no. of machine operands for DEXT!"); + else // Only DEXT and DINS are possible + assert(InstIn.getNumOperands() == 5 && + "Invalid no. of machine operands for DINS!"); + + assert(InstIn.getOperand(2).isImm()); + int64_t pos = InstIn.getOperand(2).getImm(); + assert(InstIn.getOperand(3).isImm()); + int64_t size = InstIn.getOperand(3).getImm(); + + if (size <= 32) { + if (pos < 32) // DEXT/DINS, do nothing + return; + // DEXTU/DINSU + InstIn.getOperand(2).setImm(pos - 32); + InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU); + return; + } + // DEXTM/DINSM + assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32"); + InstIn.getOperand(3).setImm(size - 32); + InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM); + return; +} + /// EncodeInstruction - Emit the instruction. -/// Size the instruction (currently only 4 bytes +/// Size the instruction with Desc.getSize(). void MipsMCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const @@ -131,14 +225,16 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, case Mips::DSLL: case Mips::DSRL: case Mips::DSRA: - Mips::LowerLargeShift(TmpInst); + case Mips::DROTR: + LowerLargeShift(TmpInst); break; // Double extract instruction is chosen by pos and size operands case Mips::DEXT: case Mips::DINS: - Mips::LowerDextDins(TmpInst); + LowerDextDins(TmpInst); } + unsigned long N = Fixups.size(); uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups); // Check for unimplemented opcodes. @@ -151,6 +247,8 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, if (STI.getFeatureBits() & Mips::FeatureMicroMips) { int NewOpcode = Mips::Std2MicroMips (Opcode, Mips::Arch_micromips); if (NewOpcode != -1) { + if (Fixups.size() > N) + Fixups.pop_back(); Opcode = NewOpcode; TmpInst.setOpcode (NewOpcode); Binary = getBinaryCodeForInstr(TmpInst, Fixups); @@ -188,6 +286,28 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, return 0; } +/// getBranchTargetOpValue - Return binary encoding of the microMIPS branch +/// target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, divide by 2. + if (MO.isImm()) return MO.getImm() >> 1; + + assert(MO.isExpr() && + "getBranchTargetOpValueMM expects only expressions or immediates"); + + const MCExpr *Expr = MO.getExpr(); + Fixups.push_back(MCFixup::Create(0, Expr, + MCFixupKind(Mips:: + fixup_MICROMIPS_PC16_S1))); + return 0; +} + /// getJumpTargetOpValue - Return binary encoding of the jump /// target operand. If the machine operand requires relocation, /// record the relocation and return zero. @@ -209,6 +329,23 @@ getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, } unsigned MipsMCCodeEmitter:: +getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + + const MCOperand &MO = MI.getOperand(OpNo); + // If the destination is an immediate, divide by 2. + if (MO.isImm()) return MO.getImm() >> 1; + + assert(MO.isExpr() && + "getJumpTargetOpValueMM expects only expressions or an immediate"); + + const MCExpr *Expr = MO.getExpr(); + Fixups.push_back(MCFixup::Create(0, Expr, + MCFixupKind(Mips::fixup_MICROMIPS_26_S1))); + return 0; +} + +unsigned MipsMCCodeEmitter:: getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const { int64_t Res; @@ -238,31 +375,39 @@ getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const { FixupKind = Mips::fixup_Mips_GPOFF_LO; break; case MCSymbolRefExpr::VK_Mips_GOT_PAGE : - FixupKind = Mips::fixup_Mips_GOT_PAGE; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_GOT_PAGE + : Mips::fixup_Mips_GOT_PAGE; break; case MCSymbolRefExpr::VK_Mips_GOT_OFST : - FixupKind = Mips::fixup_Mips_GOT_OFST; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_GOT_OFST + : Mips::fixup_Mips_GOT_OFST; break; case MCSymbolRefExpr::VK_Mips_GOT_DISP : - FixupKind = Mips::fixup_Mips_GOT_DISP; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_GOT_DISP + : Mips::fixup_Mips_GOT_DISP; break; case MCSymbolRefExpr::VK_Mips_GPREL: FixupKind = Mips::fixup_Mips_GPREL16; break; case MCSymbolRefExpr::VK_Mips_GOT_CALL: - FixupKind = Mips::fixup_Mips_CALL16; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_CALL16 + : Mips::fixup_Mips_CALL16; break; case MCSymbolRefExpr::VK_Mips_GOT16: - FixupKind = Mips::fixup_Mips_GOT_Global; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_GOT16 + : Mips::fixup_Mips_GOT_Global; break; case MCSymbolRefExpr::VK_Mips_GOT: - FixupKind = Mips::fixup_Mips_GOT_Local; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_GOT16 + : Mips::fixup_Mips_GOT_Local; break; case MCSymbolRefExpr::VK_Mips_ABS_HI: - FixupKind = Mips::fixup_Mips_HI16; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_HI16 + : Mips::fixup_Mips_HI16; break; case MCSymbolRefExpr::VK_Mips_ABS_LO: - FixupKind = Mips::fixup_Mips_LO16; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_LO16 + : Mips::fixup_Mips_LO16; break; case MCSymbolRefExpr::VK_Mips_TLSGD: FixupKind = Mips::fixup_Mips_TLSGD; @@ -271,19 +416,23 @@ getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const { FixupKind = Mips::fixup_Mips_TLSLDM; break; case MCSymbolRefExpr::VK_Mips_DTPREL_HI: - FixupKind = Mips::fixup_Mips_DTPREL_HI; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16 + : Mips::fixup_Mips_DTPREL_HI; break; case MCSymbolRefExpr::VK_Mips_DTPREL_LO: - FixupKind = Mips::fixup_Mips_DTPREL_LO; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16 + : Mips::fixup_Mips_DTPREL_LO; break; case MCSymbolRefExpr::VK_Mips_GOTTPREL: FixupKind = Mips::fixup_Mips_GOTTPREL; break; case MCSymbolRefExpr::VK_Mips_TPREL_HI: - FixupKind = Mips::fixup_Mips_TPREL_HI; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16 + : Mips::fixup_Mips_TPREL_HI; break; case MCSymbolRefExpr::VK_Mips_TPREL_LO: - FixupKind = Mips::fixup_Mips_TPREL_LO; + FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16 + : Mips::fixup_Mips_TPREL_LO; break; case MCSymbolRefExpr::VK_Mips_HIGHER: FixupKind = Mips::fixup_Mips_HIGHER; @@ -318,7 +467,7 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl<MCFixup> &Fixups) const { if (MO.isReg()) { unsigned Reg = MO.getReg(); - unsigned RegNo = Ctx.getRegisterInfo().getEncodingValue(Reg); + unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg); return RegNo; } else if (MO.isImm()) { return static_cast<unsigned>(MO.getImm()); @@ -344,6 +493,17 @@ MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, return (OffBits & 0xFFFF) | RegBits; } +unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + // Base register is encoded in bits 20-16, offset is encoded in bits 11-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 & 0x0FFF) | RegBits; +} + unsigned MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups) const { @@ -365,5 +525,13 @@ MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, return Position + Size - 1; } +unsigned +MipsMCCodeEmitter::getLSAImmEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups) const { + assert(MI.getOperand(OpNo).isImm()); + // The immediate is encoded as 'immediate - 1'. + return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups) - 1; +} + #include "MipsGenMCCodeEmitter.inc" |