From e7856db5836be46ec59f5c4a2396908ccd5c011a Mon Sep 17 00:00:00 2001 From: Bradley Smith Date: Thu, 15 May 2014 11:07:57 +0000 Subject: [PATCH] [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 --- lib/Target/ARM64/ARM64InstrFormats.td | 97 +++++++++++-------- lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp | 50 +++------- .../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 : 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, ImmLeaf { + let ParserMatchClass = VectorIndex1Operand; + let PrintMethod = "printVectorIndex"; + let MIOperandInfo = (ops i64imm); +} +def VectorIndexB : Operand, ImmLeaf { + let ParserMatchClass = VectorIndexBOperand; + let PrintMethod = "printVectorIndex"; + let MIOperandInfo = (ops i64imm); +} +def VectorIndexH : Operand, ImmLeaf { + let ParserMatchClass = VectorIndexHOperand; + let PrintMethod = "printVectorIndex"; + let MIOperandInfo = (ops i64imm); +} +def VectorIndexS : Operand, ImmLeaf { + let ParserMatchClass = VectorIndexSOperand; + let PrintMethod = "printVectorIndex"; + let MIOperandInfo = (ops i64imm); +} +def VectorIndexD : Operand, ImmLeaf { + 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 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 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 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 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 { // AdvSIMD //---------------------------------------------------------------------------- -class AsmVectorIndex : 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, ImmLeaf { - let ParserMatchClass = VectorIndexBOperand; - let PrintMethod = "printVectorIndex"; - let MIOperandInfo = (ops i64imm); -} -def VectorIndexH : Operand, ImmLeaf { - let ParserMatchClass = VectorIndexHOperand; - let PrintMethod = "printVectorIndex"; - let MIOperandInfo = (ops i64imm); -} -def VectorIndexS : Operand, ImmLeaf { - let ParserMatchClass = VectorIndexSOperand; - let PrintMethod = "printVectorIndex"; - let MIOperandInfo = (ops i64imm); -} -def VectorIndexD : Operand, ImmLeaf { - 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(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(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)); -- 2.34.1