summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/AsmParser
diff options
context:
space:
mode:
authorStepan Dyatkovskiy <stpworld@narod.ru>2014-04-24 06:03:01 +0000
committerStepan Dyatkovskiy <stpworld@narod.ru>2014-04-24 06:03:01 +0000
commit00dcc0f53c36fec51579ced2b933cf3fff6955c5 (patch)
tree4b7877a0de4020ff4880432b0c41f1a6c5a1c2c6 /llvm/lib/Target/ARM/AsmParser
parentdc493cf13baad5543aec8555c25302e2440f2320 (diff)
downloadbcm5719-llvm-00dcc0f53c36fec51579ced2b933cf3fff6955c5.tar.gz
bcm5719-llvm-00dcc0f53c36fec51579ced2b933cf3fff6955c5.zip
Fix for PR18921, "vmov" part.
Added support for bytes replication feature, so it could be GAS compatible. E.g. instructions below: "vmov.i32 d0, 0xffffffff" "vmvn.i32 d0, 0xabababab" "vmov.i32 d0, 0xabababab" "vmov.i16 d0, 0xabab" are incorrect, but we could deal with such cases. For first one we should emit: "vmov.i8 d0, 0xff" For second one ("vmvn"): "vmov.i8 d0, 0x54" For last two instructions it should emit: "vmov.i8 d0, 0xab" P.S.: In ARMAsmParser.cpp I have also fixed few nearby style issues in old code. Just for keeping method bodies in harmony with themselves. llvm-svn: 207080
Diffstat (limited to 'llvm/lib/Target/ARM/AsmParser')
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp65
1 files changed, 61 insertions, 4 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index f661d8a4beb..71b558d46bb 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -1610,7 +1610,10 @@ public:
}
bool isNEONi16splat() const {
- if (!isImm()) return false;
+ if (isNEONByteReplicate(2))
+ return false; // Leave that for bytes replication and forbid by default.
+ if (!isImm())
+ return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
// Must be a constant.
if (!CE) return false;
@@ -1620,7 +1623,10 @@ public:
}
bool isNEONi32splat() const {
- if (!isImm()) return false;
+ if (isNEONByteReplicate(4))
+ return false; // Leave that for bytes replication and forbid by default.
+ if (!isImm())
+ return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
// Must be a constant.
if (!CE) return false;
@@ -1632,11 +1638,36 @@ public:
(Value >= 0x01000000 && Value <= 0xff000000);
}
+ bool isNEONByteReplicate(unsigned NumBytes) const {
+ if (!isImm())
+ return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ // Must be a constant.
+ if (!CE)
+ return false;
+ int64_t Value = CE->getValue();
+ if (!Value)
+ return false; // Don't bother with zero.
+
+ unsigned char B = Value & 0xff;
+ for (unsigned i = 1; i < NumBytes; ++i) {
+ Value >>= 8;
+ if ((Value & 0xff) != B)
+ return false;
+ }
+ return true;
+ }
+ bool isNEONi16ByteReplicate() const { return isNEONByteReplicate(2); }
+ bool isNEONi32ByteReplicate() const { return isNEONByteReplicate(4); }
bool isNEONi32vmov() const {
- if (!isImm()) return false;
+ if (isNEONByteReplicate(4))
+ return false; // Let it to be classified as byte-replicate case.
+ if (!isImm())
+ return false;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
// Must be a constant.
- if (!CE) return false;
+ if (!CE)
+ return false;
int64_t Value = CE->getValue();
// i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
// for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
@@ -2384,6 +2415,19 @@ public:
Inst.addOperand(MCOperand::CreateImm(Value));
}
+ void addNEONinvByteReplicateOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // The immediate encodes the type of constant as well as the value.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ unsigned Value = CE->getValue();
+ assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
+ Inst.getOpcode() == ARM::VMOVv16i8) &&
+ "All vmvn instructions that wants to replicate non-zero byte "
+ "always must be replaced with VMOVv8i8 or VMOVv16i8.");
+ unsigned B = ((~Value) & 0xff);
+ B |= 0xe00; // cmode = 0b1110
+ Inst.addOperand(MCOperand::CreateImm(B));
+ }
void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The immediate encodes the type of constant as well as the value.
@@ -2398,6 +2442,19 @@ public:
Inst.addOperand(MCOperand::CreateImm(Value));
}
+ void addNEONvmovByteReplicateOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ // The immediate encodes the type of constant as well as the value.
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ unsigned Value = CE->getValue();
+ assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
+ Inst.getOpcode() == ARM::VMOVv16i8) &&
+ "All instructions that wants to replicate non-zero byte "
+ "always must be replaced with VMOVv8i8 or VMOVv16i8.");
+ unsigned B = Value & 0xff;
+ B |= 0xe00; // cmode = 0b1110
+ Inst.addOperand(MCOperand::CreateImm(B));
+ }
void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The immediate encodes the type of constant as well as the value.
OpenPOWER on IntegriCloud