Index: src/IceInstARM32.cpp |
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp |
index c1e382ab572238b28126b785f8feeaa38c498079..aff4ef335ab2486335468c852a9a51eab7871c24 100644 |
--- a/src/IceInstARM32.cpp |
+++ b/src/IceInstARM32.cpp |
@@ -382,6 +382,16 @@ InstARM32Vcvt::InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, |
addSource(Src); |
} |
+InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1, |
+ CondARM32::Cond Predicate) |
+ : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) { |
+ addSource(Src0); |
+ addSource(Src1); |
+} |
+ |
+InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate) |
+ : InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) {} |
+ |
// ======================== Dump routines ======================== // |
// Two-addr ops |
@@ -507,8 +517,7 @@ void InstARM32Vmov::emitMultiDestSingleSource(const Cfg *Func) const { |
assert(!llvm::isa<OperandARM32Mem>(Src0)); |
Str << "\t" |
- << "vmov" |
- << "\t"; |
+ << "vmov" << getPredicate() << "\t"; |
Dest0->emit(Func); |
Str << ", "; |
Dest1->emit(Func); |
@@ -529,8 +538,7 @@ void InstARM32Vmov::emitSingleDestMultiSource(const Cfg *Func) const { |
assert(!llvm::isa<OperandARM32Mem>(Src1)); |
Str << "\t" |
- << "vmov" |
- << "\t"; |
+ << "vmov" << getPredicate() << "\t"; |
Dest0->emit(Func); |
Str << ", "; |
Src0->emit(Func); |
@@ -549,6 +557,14 @@ bool isVariableWithoutRegister(const Operand *Op) { |
bool isMemoryAccess(Operand *Op) { |
return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op); |
} |
+ |
+bool isMoveBetweenCoreAndVFPRegisters(Variable *Dest, Operand *Src) { |
+ const Type DestTy = Dest->getType(); |
+ const Type SrcTy = Src->getType(); |
+ assert(!(isScalarIntegerType(DestTy) && isScalarIntegerType(SrcTy)) && |
+ "At most one of vmov's operands can be a core register."); |
+ return isScalarIntegerType(DestTy) || isScalarIntegerType(SrcTy); |
+} |
} // end of anonymous namespace |
void InstARM32Vmov::emitSingleDestSingleSource(const Cfg *Func) const { |
@@ -559,7 +575,14 @@ void InstARM32Vmov::emitSingleDestSingleSource(const Cfg *Func) const { |
if (Dest->hasReg()) { |
Operand *Src0 = getSrc(0); |
const char *ActualOpcode = isMemoryAccess(Src0) ? "vldr" : "vmov"; |
- Str << "\t" << ActualOpcode << "\t"; |
+ // when vmov{c}'ing, we need to emit a width string. Otherwise, the |
+ // assembler might be tempted to assume we want a vector vmov{c}, and that |
+ // is disallowed because ARM. |
+ const char *WidthString = |
+ (isMemoryAccess(Src0) || isMoveBetweenCoreAndVFPRegisters(Dest, Src0)) |
+ ? "" |
+ : getVecWidthString(Src0->getType()); |
+ Str << "\t" << ActualOpcode << getPredicate() << WidthString << "\t"; |
Dest->emit(Func); |
Str << ", "; |
Src0->emit(Func); |
@@ -567,8 +590,7 @@ void InstARM32Vmov::emitSingleDestSingleSource(const Cfg *Func) const { |
Variable *Src0 = llvm::cast<Variable>(getSrc(0)); |
assert(Src0->hasReg()); |
Str << "\t" |
- "vstr" |
- "\t"; |
+ "vstr" << getPredicate() << "\t"; |
Src0->emit(Func); |
Str << ", "; |
Dest->emit(Func); |
@@ -578,7 +600,6 @@ void InstARM32Vmov::emitSingleDestSingleSource(const Cfg *Func) const { |
void InstARM32Vmov::emit(const Cfg *Func) const { |
if (!BuildDefs::dump()) |
return; |
- assert(CondARM32::AL == getPredicate()); |
assert(isMultiDest() + isMultiSource() <= 1 && "Invalid vmov type."); |
if (isMultiDest()) { |
emitMultiDestSingleSource(Func); |
@@ -1045,6 +1066,59 @@ void InstARM32Vcvt::dump(const Cfg *Func) const { |
dumpSources(Func); |
} |
+void InstARM32Vcmp::emit(const Cfg *Func) const { |
+ if (!BuildDefs::dump()) |
+ return; |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ assert(getSrcSize() == 2); |
+ Str << "\t" |
+ "vcmp" << getPredicate() << getVecWidthString(getSrc(0)->getType()) |
+ << "\t"; |
+ getSrc(0)->emit(Func); |
+ Str << ", "; |
+ getSrc(1)->emit(Func); |
+} |
+ |
+void InstARM32Vcmp::emitIAS(const Cfg *Func) const { |
+ assert(getSrcSize() == 2); |
+ (void)Func; |
+ llvm_unreachable("Not yet implemented"); |
+} |
+ |
+void InstARM32Vcmp::dump(const Cfg *Func) const { |
+ if (!BuildDefs::dump()) |
+ return; |
+ Ostream &Str = Func->getContext()->getStrDump(); |
+ Str << "vcmp" << getPredicate() << getVecWidthString(getSrc(0)->getType()); |
+ dumpSources(Func); |
+} |
+ |
+void InstARM32Vmrs::emit(const Cfg *Func) const { |
+ if (!BuildDefs::dump()) |
+ return; |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ assert(getSrcSize() == 0); |
+ Str << "\t" |
+ "vmrs" << getPredicate() << "\t" |
+ "APSR_nzcv" |
+ ", " |
+ "FPSCR"; |
+} |
+ |
+void InstARM32Vmrs::emitIAS(const Cfg *Func) const { |
+ assert(getSrcSize() == 0); |
+ (void)Func; |
+ llvm_unreachable("Not yet implemented"); |
+} |
+ |
+void InstARM32Vmrs::dump(const Cfg *Func) const { |
+ if (!BuildDefs::dump()) |
+ return; |
+ Ostream &Str = Func->getContext()->getStrDump(); |
+ Str << "APSR{n,z,v,c} = vmrs" << getPredicate() << "\t" |
+ "FPSCR{n,z,c,v}"; |
+} |
+ |
void OperandARM32Mem::emit(const Cfg *Func) const { |
if (!BuildDefs::dump()) |
return; |