diff options
author | Bradley Smith <bradley.smith@arm.com> | 2014-05-15 11:07:57 +0000 |
---|---|---|
committer | Bradley Smith <bradley.smith@arm.com> | 2014-05-15 11:07:57 +0000 |
commit | e7856db5836be46ec59f5c4a2396908ccd5c011a (patch) | |
tree | f1bf81e0589b119680f722d7439b96e06e768d53 /lib/Target | |
parent | dbe4f8b96ee171244ba3ab69f0bd50b693304222 (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.td | 97 | ||||
-rw-r--r-- | lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp | 50 | ||||
-rw-r--r-- | lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp | 26 |
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)); |