summaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
authorBradley Smith <bradley.smith@arm.com>2014-05-15 11:07:57 +0000
committerBradley Smith <bradley.smith@arm.com>2014-05-15 11:07:57 +0000
commite7856db5836be46ec59f5c4a2396908ccd5c011a (patch)
treef1bf81e0589b119680f722d7439b96e06e768d53 /lib/Target
parentdbe4f8b96ee171244ba3ab69f0bd50b693304222 (diff)
[ARM64] Parse fixed vector lanes properly so that diagnostics can be emitted
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@208863 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/ARM64/ARM64InstrFormats.td97
-rw-r--r--lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp50
-rw-r--r--lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp26
3 files changed, 92 insertions, 81 deletions
diff --git a/lib/Target/ARM64/ARM64InstrFormats.td b/lib/Target/ARM64/ARM64InstrFormats.td
index 27ee48e7cf9..edbdfec7e5a 100644
--- a/lib/Target/ARM64/ARM64InstrFormats.td
+++ b/lib/Target/ARM64/ARM64InstrFormats.td
@@ -690,6 +690,53 @@ def fpimm0 : PatLeaf<(fpimm), [{
return N->isExactlyValue(+0.0);
}]>;
+// Vector lane operands
+class AsmVectorIndex<string Suffix> : AsmOperandClass {
+ let Name = "VectorIndex" # Suffix;
+ let DiagnosticType = "InvalidIndex" # Suffix;
+}
+def VectorIndex1Operand : AsmVectorIndex<"1">;
+def VectorIndexBOperand : AsmVectorIndex<"B">;
+def VectorIndexHOperand : AsmVectorIndex<"H">;
+def VectorIndexSOperand : AsmVectorIndex<"S">;
+def VectorIndexDOperand : AsmVectorIndex<"D">;
+
+def VectorIndex1 : Operand<i64>, ImmLeaf<i64, [{
+ return ((uint64_t)Imm) == 1;
+}]> {
+ let ParserMatchClass = VectorIndex1Operand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i64imm);
+}
+def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
+ return ((uint64_t)Imm) < 16;
+}]> {
+ let ParserMatchClass = VectorIndexBOperand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i64imm);
+}
+def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
+ return ((uint64_t)Imm) < 8;
+}]> {
+ let ParserMatchClass = VectorIndexHOperand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i64imm);
+}
+def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
+ return ((uint64_t)Imm) < 4;
+}]> {
+ let ParserMatchClass = VectorIndexSOperand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i64imm);
+}
+def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
+ return ((uint64_t)Imm) < 2;
+}]> {
+ let ParserMatchClass = VectorIndexDOperand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i64imm);
+}
+
// 8-bit immediate for AdvSIMD where 64-bit values of the form:
// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
// are encoded as the eight bit value 'abcdefgh'.
@@ -3409,8 +3456,8 @@ let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
RegisterClass srcType, RegisterOperand dstType, string asm,
string kind>
- : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
- "{\t$Rd"#kind#"[1], $Rn|"#kind#"\t$Rd[1], $Rn}", "", []>,
+ : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
+ "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
Sched<[WriteFCopy]> {
bits<5> Rd;
bits<5> Rn;
@@ -3421,14 +3468,16 @@ class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
let Inst{15-10} = 0b000000;
let Inst{9-5} = Rn;
let Inst{4-0} = Rd;
+
+ let DecoderMethod = "DecodeFMOVLaneInstruction";
}
let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
RegisterOperand srcType, RegisterClass dstType, string asm,
string kind>
- : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
- "{\t$Rd, $Rn"#kind#"[1]|"#kind#"\t$Rd, $Rn[1]}", "", []>,
+ : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
+ "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
Sched<[WriteFCopy]> {
bits<5> Rd;
bits<5> Rn;
@@ -3439,6 +3488,8 @@ class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
let Inst{15-10} = 0b000000;
let Inst{9-5} = Rn;
let Inst{4-0} = Rd;
+
+ let DecoderMethod = "DecodeFMOVLaneInstruction";
}
@@ -3810,44 +3861,6 @@ multiclass FPMoveImmediate<string asm> {
// AdvSIMD
//----------------------------------------------------------------------------
-class AsmVectorIndex<string Suffix> : AsmOperandClass {
- let Name = "VectorIndex" # Suffix;
- let DiagnosticType = "InvalidIndex" # Suffix;
-}
-def VectorIndexBOperand : AsmVectorIndex<"B">;
-def VectorIndexHOperand : AsmVectorIndex<"H">;
-def VectorIndexSOperand : AsmVectorIndex<"S">;
-def VectorIndexDOperand : AsmVectorIndex<"D">;
-
-def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
- return ((uint64_t)Imm) < 16;
-}]> {
- let ParserMatchClass = VectorIndexBOperand;
- let PrintMethod = "printVectorIndex";
- let MIOperandInfo = (ops i64imm);
-}
-def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
- return ((uint64_t)Imm) < 8;
-}]> {
- let ParserMatchClass = VectorIndexHOperand;
- let PrintMethod = "printVectorIndex";
- let MIOperandInfo = (ops i64imm);
-}
-def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
- return ((uint64_t)Imm) < 4;
-}]> {
- let ParserMatchClass = VectorIndexSOperand;
- let PrintMethod = "printVectorIndex";
- let MIOperandInfo = (ops i64imm);
-}
-def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
- return ((uint64_t)Imm) < 2;
-}]> {
- let ParserMatchClass = VectorIndexDOperand;
- let PrintMethod = "printVectorIndex";
- let MIOperandInfo = (ops i64imm);
-}
-
def MemorySIMDNoIndexOperand : AsmOperandClass {
let Name = "MemorySIMDNoIndex";
let ParserMethod = "tryParseNoIndexMemory";
diff --git a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
index acfc7cfe0a7..a1f0c6aa3ed 100644
--- a/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
+++ b/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
@@ -831,6 +831,9 @@ public:
return VectorList.NumElements == NumElements;
}
+ bool isVectorIndex1() const {
+ return Kind == k_VectorIndex && VectorIndex.Val == 1;
+ }
bool isVectorIndexB() const {
return Kind == k_VectorIndex && VectorIndex.Val < 16;
}
@@ -1217,6 +1220,11 @@ public:
MCOperand::CreateReg(FirstReg + getVectorListStart() - ARM64::Q0));
}
+ void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
+ }
+
void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
@@ -3782,6 +3790,8 @@ bool ARM64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode) {
return Error(Loc, "immediate must be an integer in range [1, 32].");
case Match_InvalidImm1_64:
return Error(Loc, "immediate must be an integer in range [1, 64].");
+ case Match_InvalidIndex1:
+ return Error(Loc, "expected lane specifier '[1]'");
case Match_InvalidIndexB:
return Error(Loc, "vector lane must be an integer in range [0, 15].");
case Match_InvalidIndexH:
@@ -4062,45 +4072,6 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
}
}
- // FIXME: Horrible hack to handle the literal .d[1] vector index on
- // FMOV instructions. The index isn't an actual instruction operand
- // but rather syntactic sugar. It really should be part of the mnemonic,
- // not the operand, but whatever.
- if ((NumOperands == 5) && Tok == "fmov") {
- // If the last operand is a vectorindex of '1', then replace it with
- // a '[' '1' ']' token sequence, which is what the matcher
- // (annoyingly) expects for a literal vector index operand.
- ARM64Operand *Op = static_cast<ARM64Operand *>(Operands[NumOperands - 1]);
- if (Op->isVectorIndexD() && Op->getVectorIndex() == 1) {
- SMLoc Loc = Op->getStartLoc();
- Operands.pop_back();
- delete Op;
- Operands.push_back(
- ARM64Operand::CreateToken("[", false, Loc, getContext()));
- Operands.push_back(
- ARM64Operand::CreateToken("1", false, Loc, getContext()));
- Operands.push_back(
- ARM64Operand::CreateToken("]", false, Loc, getContext()));
- } else if (Op->isReg()) {
- // Similarly, check the destination operand for the GPR->High-lane
- // variant.
- unsigned OpNo = NumOperands - 2;
- ARM64Operand *Op = static_cast<ARM64Operand *>(Operands[OpNo]);
- if (Op->isVectorIndexD() && Op->getVectorIndex() == 1) {
- SMLoc Loc = Op->getStartLoc();
- Operands[OpNo] =
- ARM64Operand::CreateToken("[", false, Loc, getContext());
- Operands.insert(
- Operands.begin() + OpNo + 1,
- ARM64Operand::CreateToken("1", false, Loc, getContext()));
- Operands.insert(
- Operands.begin() + OpNo + 2,
- ARM64Operand::CreateToken("]", false, Loc, getContext()));
- delete Op;
- }
- }
- }
-
MCInst Inst;
// First try to match against the secondary set of tables containing the
// short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
@@ -4216,6 +4187,7 @@ bool ARM64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidImm1_16:
case Match_InvalidImm1_32:
case Match_InvalidImm1_64:
+ case Match_InvalidIndex1:
case Match_InvalidIndexB:
case Match_InvalidIndexH:
case Match_InvalidIndexS:
diff --git a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp
index de87d5dcfdd..d14e3a86f8f 100644
--- a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp
+++ b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp
@@ -144,6 +144,9 @@ static DecodeStatus DecodeSystemPStateInstruction(llvm::MCInst &Inst,
static DecodeStatus DecodeTestAndBranch(llvm::MCInst &Inst, uint32_t insn,
uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
static DecodeStatus DecodeVecShiftR64Imm(llvm::MCInst &Inst, unsigned Imm,
uint64_t Addr, const void *Decoder);
static DecodeStatus DecodeVecShiftR64ImmNarrow(llvm::MCInst &Inst, unsigned Imm,
@@ -634,6 +637,29 @@ static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm,
return ValidNamed ? Success : Fail;
}
+static DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn,
+ uint64_t Address,
+ const void *Decoder) {
+ // This decoder exists to add the dummy Lane operand to the MCInst, which must
+ // be 1 in assembly but has no other real manifestation.
+ unsigned Rd = fieldFromInstruction(Insn, 0, 5);
+ unsigned Rn = fieldFromInstruction(Insn, 5, 5);
+ unsigned IsToVec = fieldFromInstruction(Insn, 16, 1);
+
+ if (IsToVec) {
+ DecodeFPR128RegisterClass(Inst, Rd, Address, Decoder);
+ DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder);
+ } else {
+ DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder);
+ DecodeFPR128RegisterClass(Inst, Rn, Address, Decoder);
+ }
+
+ // Add the lane
+ Inst.addOperand(MCOperand::CreateImm(1));
+
+ return Success;
+}
+
static DecodeStatus DecodeVecShiftRImm(llvm::MCInst &Inst, unsigned Imm,
unsigned Add) {
Inst.addOperand(MCOperand::CreateImm(Add - Imm));