diff options
Diffstat (limited to 'lib/Target/Mips/Mips16InstrInfo.cpp')
-rw-r--r-- | lib/Target/Mips/Mips16InstrInfo.cpp | 62 |
1 files changed, 56 insertions, 6 deletions
diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp index 05e70ab..000ea28 100644 --- a/lib/Target/Mips/Mips16InstrInfo.cpp +++ b/lib/Target/Mips/Mips16InstrInfo.cpp @@ -10,7 +10,6 @@ // This file contains the Mips16 implementation of the TargetInstrInfo class. // //===----------------------------------------------------------------------===// -#include <stdio.h> #include "Mips16InstrInfo.h" #include "InstPrinter/MipsInstPrinter.h" #include "MipsMachineFunction.h" @@ -20,10 +19,12 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" +#include <cctype> using namespace llvm; @@ -36,7 +37,7 @@ static cl::opt<bool> NeverUseSaveRestore( Mips16InstrInfo::Mips16InstrInfo(MipsTargetMachine &tm) - : MipsInstrInfo(tm, Mips::BimmX16), + : MipsInstrInfo(tm, Mips::Bimm16), RI(*tm.getSubtargetImpl()) {} const MipsRegisterInfo &Mips16InstrInfo::getRegisterInfo() const { @@ -77,11 +78,11 @@ void Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB, else if (Mips::GPR32RegClass.contains(DestReg) && Mips::CPU16RegsRegClass.contains(SrcReg)) Opc = Mips::Move32R16; - else if ((SrcReg == Mips::HI) && + else if ((SrcReg == Mips::HI0) && (Mips::CPU16RegsRegClass.contains(DestReg))) Opc = Mips::Mfhi16, SrcReg = 0; - else if ((SrcReg == Mips::LO) && + else if ((SrcReg == Mips::LO0) && (Mips::CPU16RegsRegClass.contains(DestReg))) Opc = Mips::Mflo16, SrcReg = 0; @@ -151,13 +152,17 @@ unsigned Mips16InstrInfo::getOppositeBranchOpc(unsigned Opc) const { default: llvm_unreachable("Illegal opcode!"); case Mips::BeqzRxImmX16: return Mips::BnezRxImmX16; case Mips::BnezRxImmX16: return Mips::BeqzRxImmX16; + case Mips::BeqzRxImm16: return Mips::BnezRxImm16; + case Mips::BnezRxImm16: return Mips::BeqzRxImm16; case Mips::BteqzT8CmpX16: return Mips::BtnezT8CmpX16; case Mips::BteqzT8SltX16: return Mips::BtnezT8SltX16; case Mips::BteqzT8SltiX16: return Mips::BtnezT8SltiX16; + case Mips::Btnez16: return Mips::Bteqz16; case Mips::BtnezX16: return Mips::BteqzX16; case Mips::BtnezT8CmpiX16: return Mips::BteqzT8CmpiX16; case Mips::BtnezT8SltuX16: return Mips::BteqzT8SltuX16; case Mips::BtnezT8SltiuX16: return Mips::BteqzT8SltiuX16; + case Mips::Bteqz16: return Mips::Btnez16; case Mips::BteqzX16: return Mips::BtnezX16; case Mips::BteqzT8CmpiX16: return Mips::BtnezT8CmpiX16; case Mips::BteqzT8SltuX16: return Mips::BtnezT8SltuX16; @@ -439,6 +444,9 @@ Mips16InstrInfo::basicLoadImmediate( unsigned Mips16InstrInfo::getAnalyzableBrOpc(unsigned Opc) const { return (Opc == Mips::BeqzRxImmX16 || Opc == Mips::BimmX16 || + Opc == Mips::Bimm16 || + Opc == Mips::Bteqz16 || Opc == Mips::Btnez16 || + Opc == Mips::BeqzRxImm16 || Opc == Mips::BnezRxImm16 || Opc == Mips::BnezRxImmX16 || Opc == Mips::BteqzX16 || Opc == Mips::BteqzT8CmpX16 || Opc == Mips::BteqzT8CmpiX16 || Opc == Mips::BteqzT8SltX16 || Opc == Mips::BteqzT8SltuX16 || @@ -473,7 +481,6 @@ const MipsInstrInfo *llvm::createMips16InstrInfo(MipsTargetMachine &TM) { return new Mips16InstrInfo(TM); } -#include <stdio.h> bool Mips16InstrInfo::validImmediate(unsigned Opcode, unsigned Reg, int64_t Amount) { switch (Opcode) { @@ -493,6 +500,49 @@ bool Mips16InstrInfo::validImmediate(unsigned Opcode, unsigned Reg, return isInt<16>(Amount); return isInt<15>(Amount); } - printf("Unexpected opcode %i \n", Opcode); llvm_unreachable("unexpected Opcode in validImmediate"); } + +/// Measure the specified inline asm to determine an approximation of its +/// length. +/// Comments (which run till the next SeparatorString or newline) do not +/// count as an instruction. +/// Any other non-whitespace text is considered an instruction, with +/// multiple instructions separated by SeparatorString or newlines. +/// Variable-length instructions are not handled here; this function +/// may be overloaded in the target code to do that. +/// We implement the special case of the .space directive taking only an +/// integer argument, which is the size in bytes. This is used for creating +/// inline code spacing for testing purposes using inline assembly. +/// +unsigned Mips16InstrInfo::getInlineAsmLength(const char *Str, + const MCAsmInfo &MAI) const { + + + // Count the number of instructions in the asm. + bool atInsnStart = true; + unsigned Length = 0; + for (; *Str; ++Str) { + if (*Str == '\n' || strncmp(Str, MAI.getSeparatorString(), + strlen(MAI.getSeparatorString())) == 0) + atInsnStart = true; + if (atInsnStart && !std::isspace(static_cast<unsigned char>(*Str))) { + if (strncmp(Str, ".space", 6)==0) { + char *EStr; int Sz; + Sz = strtol(Str+6, &EStr, 10); + while (isspace(*EStr)) ++EStr; + if (*EStr=='\0') { + DEBUG(dbgs() << "parsed .space " << Sz << '\n'); + return Sz; + } + } + Length += MAI.getMaxInstLength(); + atInsnStart = false; + } + if (atInsnStart && strncmp(Str, MAI.getCommentString(), + strlen(MAI.getCommentString())) == 0) + atInsnStart = false; + } + + return Length; +} |