Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Unified Diff: src/IceInstARM32.cpp

Issue 1359193003: Subzero. Enables (most) crosstests for ARM32. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceInstARM32.h ('k') | src/IceInstARM32.def » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceInstARM32.cpp
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
index aff4ef335ab2486335468c852a9a51eab7871c24..99584dc010349319244437752d2b19b0ba99b2e3 100644
--- a/src/IceInstARM32.cpp
+++ b/src/IceInstARM32.cpp
@@ -33,7 +33,7 @@ const struct TypeARM32Attributes_ {
int8_t SExtAddrOffsetBits;
int8_t ZExtAddrOffsetBits;
} TypeARM32Attributes[] = {
-#define X(tag, elementty, int_width, vec_width, sbits, ubits) \
+#define X(tag, elementty, int_width, vec_width, sbits, ubits, rraddr) \
{ int_width, vec_width, sbits, ubits } \
,
ICETYPEARM32_TABLE
@@ -211,8 +211,6 @@ bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
return Offset == 0;
// Note that encodings for offsets are sign-magnitude for ARM, so we check
// with IsAbsoluteUint().
- if (isScalarFloatingType(Ty))
- return Utils::IsAligned(Offset, 4) && Utils::IsAbsoluteUint(Bits, Offset);
return Utils::IsAbsoluteUint(Bits, Offset);
}
@@ -392,6 +390,11 @@ InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1,
InstARM32Vmrs::InstARM32Vmrs(Cfg *Func, CondARM32::Cond Predicate)
: InstARM32Pred(Func, InstARM32::Vmrs, 0, nullptr, Predicate) {}
+InstARM32Vabs::InstARM32Vabs(Cfg *Func, Variable *Dest, Variable *Src,
+ CondARM32::Cond Predicate)
+ : InstARM32Pred(Func, InstARM32::Vabs, 1, Dest, Predicate) {
+ addSource(Src);
+}
// ======================== Dump routines ======================== //
// Two-addr ops
@@ -408,9 +411,6 @@ template <> const char *InstARM32Uxt::Opcode = "uxt"; // still requires b/h
template <> const char *InstARM32Vsqrt::Opcode = "vsqrt";
// Mov-like ops
template <> const char *InstARM32Ldr::Opcode = "ldr";
-template <> const char *InstARM32Mov::Opcode = "mov";
-// FP
-template <> const char *InstARM32Vldr::Opcode = "vldr";
// Three-addr ops
template <> const char *InstARM32Adc::Opcode = "adc";
template <> const char *InstARM32Add::Opcode = "add";
@@ -447,113 +447,56 @@ void InstARM32::dump(const Cfg *Func) const {
Inst::dump(Func);
}
-template <> void InstARM32Mov::emit(const Cfg *Func) const {
- if (!BuildDefs::dump())
- return;
- Ostream &Str = Func->getContext()->getStrEmit();
- assert(getSrcSize() == 1);
- Variable *Dest = getDest();
- if (Dest->hasReg()) {
- IceString ActualOpcode = Opcode;
- Operand *Src0 = getSrc(0);
- if (const auto *Src0V = llvm::dyn_cast<Variable>(Src0)) {
- if (!Src0V->hasReg()) {
- // Always use the whole stack slot. A 32-bit load has a larger range of
- // offsets than 16-bit, etc.
- ActualOpcode = IceString("ldr");
- }
- } else {
- if (llvm::isa<OperandARM32Mem>(Src0))
- ActualOpcode = IceString("ldr") + getWidthString(Dest->getType());
- }
- Str << "\t" << ActualOpcode << getPredicate() << "\t";
- getDest()->emit(Func);
- Str << ", ";
- getSrc(0)->emit(Func);
- } else {
- Variable *Src0 = llvm::cast<Variable>(getSrc(0));
- assert(Src0->hasReg());
- Str << "\t"
- << "str" << getPredicate() << "\t";
- Src0->emit(Func);
- Str << ", ";
- Dest->emit(Func);
- }
-}
-
-template <> void InstARM32Mov::emitIAS(const Cfg *Func) const {
- assert(getSrcSize() == 1);
- (void)Func;
- llvm_unreachable("Not yet implemented");
-}
-
-template <> void InstARM32Vldr::emit(const Cfg *Func) const {
+void InstARM32Mov::emitMultiDestSingleSource(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
- assert(getSrcSize() == 1);
- assert(getDest()->hasReg());
- Str << "\t" << Opcode << getPredicate() << "\t";
- getDest()->emit(Func);
- Str << ", ";
- getSrc(0)->emit(Func);
-}
+ auto *Dest = llvm::cast<Variable64On32>(getDest());
+ Operand *Src = getSrc(0);
-template <> void InstARM32Vldr::emitIAS(const Cfg *Func) const {
- assert(getSrcSize() == 1);
- (void)Func;
- llvm_unreachable("Not yet implemented");
-}
-
-void InstARM32Vmov::emitMultiDestSingleSource(const Cfg *Func) const {
- if (!BuildDefs::dump())
- return;
- Ostream &Str = Func->getContext()->getStrEmit();
- Variable *Dest0 = getDest();
- Operand *Src0 = getSrc(0);
-
- assert(Dest0->hasReg());
- assert(Dest1->hasReg());
- assert(!llvm::isa<OperandARM32Mem>(Src0));
+ assert(Dest->getType() == IceType_i64);
+ assert(Dest->getHi()->hasReg());
+ assert(Dest->getLo()->hasReg());
+ assert(!llvm::isa<OperandARM32Mem>(Src));
Str << "\t"
<< "vmov" << getPredicate() << "\t";
- Dest0->emit(Func);
+ Dest->getLo()->emit(Func);
Str << ", ";
- Dest1->emit(Func);
+ Dest->getHi()->emit(Func);
Str << ", ";
- Src0->emit(Func);
+ Src->emit(Func);
}
-void InstARM32Vmov::emitSingleDestMultiSource(const Cfg *Func) const {
+void InstARM32Mov::emitSingleDestMultiSource(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
- Variable *Dest0 = getDest();
- Operand *Src0 = getSrc(0);
- Operand *Src1 = getSrc(1);
+ Variable *Dest = getDest();
+ auto *Src = llvm::cast<Variable64On32>(getSrc(0));
- assert(Dest0->hasReg());
- assert(!llvm::isa<OperandARM32Mem>(Src0));
- assert(!llvm::isa<OperandARM32Mem>(Src1));
+ assert(Src->getType() == IceType_i64);
+ assert(Src->getHi()->hasReg());
+ assert(Src->getLo()->hasReg());
+ assert(Dest->hasReg());
Str << "\t"
<< "vmov" << getPredicate() << "\t";
- Dest0->emit(Func);
+ Dest->emit(Func);
Str << ", ";
- Src0->emit(Func);
+ Src->getLo()->emit(Func);
Str << ", ";
- Src1->emit(Func);
+ Src->getHi()->emit(Func);
}
namespace {
+
bool isVariableWithoutRegister(const Operand *Op) {
if (const auto *OpV = llvm::dyn_cast<const Variable>(Op)) {
return !OpV->hasReg();
}
return false;
}
-
bool isMemoryAccess(Operand *Op) {
return isVariableWithoutRegister(Op) || llvm::isa<OperandARM32Mem>(Op);
}
@@ -561,27 +504,38 @@ bool isMemoryAccess(Operand *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);
+ return !isVectorType(DestTy) && !isVectorType(SrcTy) &&
+ (isScalarIntegerType(DestTy) == isScalarFloatingType(SrcTy));
}
+
} // end of anonymous namespace
-void InstARM32Vmov::emitSingleDestSingleSource(const Cfg *Func) const {
+void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
Variable *Dest = getDest();
+
if (Dest->hasReg()) {
+ Type DestTy = Dest->getType();
Operand *Src0 = getSrc(0);
- const char *ActualOpcode = isMemoryAccess(Src0) ? "vldr" : "vmov";
+ const bool DestIsVector = isVectorType(DestTy);
+ const bool DestIsScalarFP = isScalarFloatingType(Dest->getType());
+ const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
+ const char *LoadOpcode =
+ DestIsVector ? "vld1" : (DestIsScalarFP ? "vldr" : "ldr");
+ const char *RegMovOpcode =
+ (DestIsVector || DestIsScalarFP || CoreVFPMove) ? "vmov" : "mov";
+ const char *ActualOpcode = isMemoryAccess(Src0) ? LoadOpcode : RegMovOpcode;
// 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 *NoWidthString = "";
const char *WidthString =
- (isMemoryAccess(Src0) || isMoveBetweenCoreAndVFPRegisters(Dest, Src0))
- ? ""
- : getVecWidthString(Src0->getType());
+ isMemoryAccess(Src0)
+ ? (DestIsVector ? ".64" : NoWidthString)
+ : (!CoreVFPMove ? getVecWidthString(DestTy) : NoWidthString);
+
Str << "\t" << ActualOpcode << getPredicate() << WidthString << "\t";
Dest->emit(Func);
Str << ", ";
@@ -589,18 +543,24 @@ void InstARM32Vmov::emitSingleDestSingleSource(const Cfg *Func) const {
} else {
Variable *Src0 = llvm::cast<Variable>(getSrc(0));
assert(Src0->hasReg());
- Str << "\t"
- "vstr" << getPredicate() << "\t";
+ const char *ActualOpcode =
+ isVectorType(Src0->getType())
+ ? "vst1"
+ : (isScalarFloatingType(Src0->getType()) ? "vstr" : "str");
+ const char *NoWidthString = "";
+ const char *WidthString =
+ isVectorType(Src0->getType()) ? ".64" : NoWidthString;
+ Str << "\t" << ActualOpcode << getPredicate() << WidthString << "\t";
Src0->emit(Func);
Str << ", ";
Dest->emit(Func);
}
}
-void InstARM32Vmov::emit(const Cfg *Func) const {
+void InstARM32Mov::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
- assert(isMultiDest() + isMultiSource() <= 1 && "Invalid vmov type.");
+ assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
if (isMultiDest()) {
emitMultiDestSingleSource(Func);
return;
@@ -614,21 +574,37 @@ void InstARM32Vmov::emit(const Cfg *Func) const {
emitSingleDestSingleSource(Func);
}
-void InstARM32Vmov::emitIAS(const Cfg *Func) const {
+void InstARM32Mov::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 1);
(void)Func;
llvm_unreachable("Not yet implemented");
}
-void InstARM32Vmov::dump(const Cfg *Func) const {
+void InstARM32Mov::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
+ assert(getSrcSize() == 1);
Ostream &Str = Func->getContext()->getStrDump();
- dumpOpcodePred(Str, "vmov", getDest()->getType());
+ Variable *Dest = getDest();
+ if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) {
+ Dest64->getLo()->dump(Func);
+ Str << ", ";
+ Dest64->getHi()->dump(Func);
+ } else {
+ Dest->dump(Func);
+ }
+
+ dumpOpcodePred(Str, " = mov", getDest()->getType());
Str << " ";
- dumpDest(Func);
- Str << ", ";
- dumpSources(Func);
+
+ Operand *Src = getSrc(0);
+ if (auto *Src64 = llvm::dyn_cast<Variable64On32>(Src)) {
+ Src64->getLo()->dump(Func);
+ Str << ", ";
+ Src64->getHi()->dump(Func);
+ } else {
+ Src->dump(Func);
+ }
}
void InstARM32Br::emit(const Cfg *Func) const {
@@ -748,8 +724,16 @@ template <> void InstARM32Ldr::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 1);
assert(getDest()->hasReg());
- Type Ty = getSrc(0)->getType();
- Str << "\t" << Opcode << getWidthString(Ty) << getPredicate() << "\t";
+ Variable *Dest = getDest();
+ Type DestTy = Dest->getType();
+ const bool DestIsVector = isVectorType(DestTy);
+ const bool DestIsScalarFloat = isScalarFloatingType(DestTy);
+ const char *ActualOpcode =
+ DestIsVector ? "vld1" : (DestIsScalarFloat ? "vldr" : "ldr");
+ const char *VectorMarker = DestIsVector ? ".64" : "";
+ const char *WidthString = DestIsVector ? "" : getWidthString(DestTy);
+ Str << "\t" << ActualOpcode << WidthString << getPredicate() << VectorMarker
+ << "\t";
getDest()->emit(Func);
Str << ", ";
getSrc(0)->emit(Func);
@@ -799,15 +783,28 @@ template <> void InstARM32Movt::emit(const Cfg *Func) const {
void InstARM32Pop::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
- assert(Dests.size() > 0);
+ SizeT IntegerCount = 0;
+ for (const Operand *Op : Dests) {
+ if (isScalarIntegerType(Op->getType())) {
+ ++IntegerCount;
+ }
+ }
Ostream &Str = Func->getContext()->getStrEmit();
+ if (IntegerCount == 0) {
+ Str << "\t@ empty pop";
+ return;
+ }
Str << "\t"
<< "pop"
<< "\t{";
- for (SizeT I = 0; I < Dests.size(); ++I) {
- if (I > 0)
- Str << ", ";
- Dests[I]->emit(Func);
+ bool PrintComma = false;
+ for (const Operand *Op : Dests) {
+ if (isScalarIntegerType(Op->getType())) {
+ if (PrintComma)
+ Str << ", ";
+ Op->emit(Func);
+ PrintComma = true;
+ }
}
Str << "}";
}
@@ -866,12 +863,31 @@ void InstARM32AdjustStack::dump(const Cfg *Func) const {
void InstARM32Push::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
- assert(getSrcSize() > 0);
+ SizeT IntegerCount = 0;
+ for (SizeT i = 0; i < getSrcSize(); ++i) {
+ if (isScalarIntegerType(getSrc(i)->getType())) {
+ ++IntegerCount;
+ }
+ }
Ostream &Str = Func->getContext()->getStrEmit();
+ if (IntegerCount == 0) {
+ Str << "\t"
+ << "@empty push";
+ return;
+ }
Str << "\t"
<< "push"
<< "\t{";
- emitSources(Func);
+ bool PrintComma = false;
+ for (SizeT i = 0; i < getSrcSize(); ++i) {
+ Operand *Op = getSrc(i);
+ if (isScalarIntegerType(Op->getType())) {
+ if (PrintComma)
+ Str << ", ";
+ Op->emit(Func);
+ PrintComma = true;
+ }
+ }
Str << "}";
}
@@ -923,8 +939,12 @@ void InstARM32Str::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 2);
Type Ty = getSrc(0)->getType();
- const char *Opcode = isScalarFloatingType(Ty) ? "vstr" : "str";
- Str << "\t" << Opcode << getWidthString(Ty) << getPredicate() << "\t";
+ const bool IsVectorStore = isVectorType(Ty);
+ const char *Opcode =
+ IsVectorStore ? "vst1" : (isScalarFloatingType(Ty) ? "vstr" : "str");
+ const char *VecEltWidthString = IsVectorStore ? ".64" : "";
+ Str << "\t" << Opcode << getWidthString(Ty) << getPredicate()
+ << VecEltWidthString << "\t";
getSrc(0)->emit(Func);
Str << ", ";
getSrc(1)->emit(Func);
@@ -1119,6 +1139,33 @@ void InstARM32Vmrs::dump(const Cfg *Func) const {
"FPSCR{n,z,c,v}";
}
+void InstARM32Vabs::emit(const Cfg *Func) const {
+ if (!BuildDefs::dump())
+ return;
+ Ostream &Str = Func->getContext()->getStrEmit();
+ assert(getSrcSize() == 1);
+ Str << "\t"
+ "vabs" << getPredicate() << getVecWidthString(getSrc(0)->getType())
+ << "\t";
+ getDest()->emit(Func);
+ Str << ", ";
+ getSrc(0)->emit(Func);
+}
+
+void InstARM32Vabs::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 1);
+ (void)Func;
+ llvm_unreachable("Not yet implemented");
+}
+
+void InstARM32Vabs::dump(const Cfg *Func) const {
+ if (!BuildDefs::dump())
+ return;
+ Ostream &Str = Func->getContext()->getStrDump();
+ dumpDest(Func);
+ Str << " = vabs" << getPredicate() << getVecWidthString(getSrc(0)->getType());
+}
+
void OperandARM32Mem::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
@@ -1128,13 +1175,13 @@ void OperandARM32Mem::emit(const Cfg *Func) const {
switch (getAddrMode()) {
case PostIndex:
case NegPostIndex:
- Str << "], ";
+ Str << "]";
break;
default:
- Str << ", ";
break;
}
if (isRegReg()) {
+ Str << ", ";
if (isNegAddrMode()) {
Str << "-";
}
@@ -1144,7 +1191,11 @@ void OperandARM32Mem::emit(const Cfg *Func) const {
<< getShiftAmt();
}
} else {
- getOffset()->emit(Func);
+ ConstantInteger32 *Offset = getOffset();
+ if (Offset && Offset->getValue() != 0) {
+ Str << ", ";
+ Offset->emit(Func);
+ }
}
switch (getAddrMode()) {
case Offset:
« no previous file with comments | « src/IceInstARM32.h ('k') | src/IceInstARM32.def » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698