Index: src/IceInstMIPS32.cpp |
diff --git a/src/IceInstMIPS32.cpp b/src/IceInstMIPS32.cpp |
index 7773272a5985272e56e5bcc92009d015cd5f510a..7a4939a7b6006100f4e86133720275cc249f43bb 100644 |
--- a/src/IceInstMIPS32.cpp |
+++ b/src/IceInstMIPS32.cpp |
@@ -12,7 +12,6 @@ |
/// constructors and the dump()/emit() methods. |
/// |
//===----------------------------------------------------------------------===// |
- |
#include "IceAssemblerMIPS32.h" |
#include "IceCfg.h" |
#include "IceCfgNode.h" |
@@ -21,14 +20,62 @@ |
#include "IceOperand.h" |
#include "IceRegistersMIPS32.h" |
#include "IceTargetLoweringMIPS32.h" |
+#include <limits> |
namespace Ice { |
+bool OperandMIPS32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) { |
+ (void)SignExt; |
+ (void)Ty; |
+ if ((std::numeric_limits<int16_t>::min() <= Offset) && |
+ (Offset <= std::numeric_limits<int16_t>::max())) |
+ return true; |
+ return false; |
+} |
+ |
+OperandMIPS32Mem::OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base, |
+ ConstantInteger32 *ImmOffset, AddrMode Mode) |
+ : OperandMIPS32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Mode(Mode) { |
+ // The Neg modes are only needed for Reg +/- Reg. |
+ (void)Func; |
+ // assert(!isNegAddrMode()); |
+ NumVars = 1; |
+ Vars = &this->Base; |
+} |
+ |
const char *InstMIPS32::getWidthString(Type Ty) { |
(void)Ty; |
return "TBD"; |
} |
+ |
+template <> const char *InstMIPS32Addiu::Opcode = "addiu"; |
+template <> const char *InstMIPS32Lui::Opcode = "lui"; |
+template <> const char *InstMIPS32La::Opcode = "la"; |
+ |
+template <> const char *InstMIPS32Ori::Opcode = "ori"; |
+ |
+InstMIPS32Mov::InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src) |
+ : InstMIPS32(Func, InstMIPS32::Mov, 2, Dest) { |
+ auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest); |
+ auto *Src64 = llvm::dyn_cast<Variable64On32>(Src); |
+ |
+ assert(Dest64 == nullptr || Src64 == nullptr); |
+ |
+ if (Dest64 != nullptr) { |
+ // this-> is needed below because there is a parameter named Dest. |
+ this->Dest = Dest64->getLo(); |
+ DestHi = Dest64->getHi(); |
+ } |
+ |
+ if (Src64 == nullptr) { |
+ addSource(Src); |
+ } else { |
+ addSource(Src64->getLo()); |
+ addSource(Src64->getHi()); |
+ } |
+} |
+ |
InstMIPS32Ret::InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source) |
: InstMIPS32(Func, InstMIPS32::Ret, Source ? 2 : 1, nullptr) { |
addSource(RA); |
@@ -46,6 +93,25 @@ void InstMIPS32::dump(const Cfg *Func) const { |
Inst::dump(Func); |
} |
+void OperandMIPS32Mem::emit(const Cfg *Func) const { |
+ if (!BuildDefs::dump()) |
+ return; |
+ llvm_unreachable("Not yet implemented"); |
+ (void)Func; |
+} |
+ |
+void InstMIPS32::emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst, |
+ const Cfg *Func) { |
+ if (!BuildDefs::dump()) |
+ return; |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ // Type SrcTy = Inst->getSrc(0)->getType(); |
+ Str << "\t" << Opcode << "\t"; |
+ Inst->getDest()->emit(Func); |
+ Str << ", "; |
+ Inst->getSrc(0)->emit(Func); |
+} |
+ |
void InstMIPS32Ret::emit(const Cfg *Func) const { |
if (!BuildDefs::dump()) |
return; |
@@ -55,7 +121,7 @@ void InstMIPS32Ret::emit(const Cfg *Func) const { |
assert(RA->getRegNum() == RegMIPS32::Reg_RA); |
Ostream &Str = Func->getContext()->getStrEmit(); |
Str << "\t" |
- << "jr $ra" |
+ << "jr" |
<< "\t"; |
RA->emit(Func); |
} |
@@ -73,4 +139,102 @@ void InstMIPS32Ret::dump(const Cfg *Func) const { |
Str << "ret." << Ty << " "; |
dumpSources(Func); |
} |
+ |
+void InstMIPS32Mov::emit(const Cfg *Func) const { |
+ if (!BuildDefs::dump()) |
+ return; |
+ assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); |
+ if (isMultiDest()) { |
+ emitMultiDestSingleSource(Func); |
+ return; |
+ } |
+ |
+ if (isMultiSource()) { |
+ emitSingleDestMultiSource(Func); |
+ return; |
+ } |
+ |
+ emitSingleDestSingleSource(Func); |
} |
+ |
+void InstMIPS32Mov::emitIAS(const Cfg *Func) const { |
+ assert(getSrcSize() == 1); |
+ (void)Func; |
+ llvm_unreachable("Not yet implemented"); |
+} |
+ |
+void InstMIPS32Mov::dump(const Cfg *Func) const { |
+ if (!BuildDefs::dump()) |
+ return; |
+ assert(getSrcSize() == 1 || getSrcSize() == 2); |
+ Ostream &Str = Func->getContext()->getStrDump(); |
+ Variable *Dest = getDest(); |
+ Variable *DestHi = getDestHi(); |
+ Dest->dump(Func); |
+ if (DestHi) { |
+ Str << ", "; |
+ DestHi->dump(Func); |
+ } |
+ |
+ dumpOpcode(Str, " = mov", getDest()->getType()); |
+ Str << " "; |
+ |
+ dumpSources(Func); |
+} |
+ |
+void InstMIPS32Mov::emitMultiDestSingleSource(const Cfg *Func) const { |
+ if (!BuildDefs::dump()) |
+ return; |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ Variable *DestLo = getDest(); |
+ Variable *DestHi = getDestHi(); |
+ auto *Src = llvm::cast<Variable>(getSrc(0)); |
+ |
+ assert(DestHi->hasReg()); |
+ assert(DestLo->hasReg()); |
+ assert(llvm::isa<Variable>(Src) && Src->hasReg()); |
+ |
+ // Str << "\t" |
+ // << "vmov" << getPredicate() << "\t"; |
+ DestLo->emit(Func); |
+ Str << ", "; |
+ DestHi->emit(Func); |
+ Str << ", "; |
+ Src->emit(Func); |
+} |
+ |
+void InstMIPS32Mov::emitSingleDestMultiSource(const Cfg *Func) const { |
+ if (!BuildDefs::dump()) |
+ return; |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ Variable *Dest = getDest(); |
+ Variable *SrcLo = llvm::cast<Variable>(getSrc(0)); |
+ Variable *SrcHi = llvm::cast<Variable>(getSrc(1)); |
+ |
+ assert(SrcHi->hasReg()); |
+ assert(SrcLo->hasReg()); |
+ assert(Dest->hasReg()); |
+ assert(getSrcSize() == 2); |
+ |
+ // Str << "\t" |
+ // << "vmov" << getPredicate() << "\t"; |
+ Dest->emit(Func); |
+ Str << ", "; |
+ SrcLo->emit(Func); |
+ Str << ", "; |
+ SrcHi->emit(Func); |
+} |
+ |
+void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const { |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ // assert(Inst->getSrcSize() == 1); |
+ // Type SrcTy = Inst->getSrc(0)->getType(); |
+ Str << "\t" |
+ << "move" |
+ << "\t"; |
+ getDest()->emit(Func); |
+ Str << ", "; |
+ getSrc(0)->emit(Func); |
+} |
+ |
+} // end of namespace Ice |