X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=lib%2FTarget%2FARM%2FAsmParser%2FARMAsmParser.cpp;h=11b6574c2866bd2fe26165784b363c540fd02c66;hb=ea46110f57b293844a314aec3b8092adf21ff63f;hp=995514c8c3b98d080291450e17b804c646168431;hpb=e53c87b302b3ae07c781405572170b0b6641b524;p=oota-llvm.git diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 995514c8c3b..11b6574c286 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -138,6 +138,8 @@ class ARMAsmParser : public MCTargetAsmParser { SmallVectorImpl&); OperandMatchResultTy parseCoprocRegOperand( SmallVectorImpl&); + OperandMatchResultTy parseCoprocOptionOperand( + SmallVectorImpl&); OperandMatchResultTy parseMemBarrierOptOperand( SmallVectorImpl&); OperandMatchResultTy parseProcIFlagsOperand( @@ -247,6 +249,7 @@ class ARMOperand : public MCParsedAsmOperand { k_ITCondMask, k_CoprocNum, k_CoprocReg, + k_CoprocOption, k_Immediate, k_FPImmediate, k_MemBarrierOpt, @@ -279,6 +282,10 @@ class ARMOperand : public MCParsedAsmOperand { unsigned Val; } Cop; + struct { + unsigned Val; + } CoprocOption; + struct { unsigned Mask:4; } ITMask; @@ -324,7 +331,9 @@ class ARMOperand : public MCParsedAsmOperand { const MCConstantExpr *OffsetImm; // Offset immediate value unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg - unsigned ShiftImm; // shift for OffsetReg. + unsigned ShiftImm; // shift for OffsetReg. + unsigned Alignment; // 0 = no alignment specified + // n = alignment in bytes (8, 16, or 32) unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit) } Memory; @@ -388,6 +397,9 @@ public: case k_CoprocReg: Cop = o.Cop; break; + case k_CoprocOption: + CoprocOption = o.CoprocOption; + break; case k_Immediate: Imm = o.Imm; break; @@ -493,6 +505,7 @@ public: bool isCoprocNum() const { return Kind == k_CoprocNum; } bool isCoprocReg() const { return Kind == k_CoprocReg; } + bool isCoprocOption() const { return Kind == k_CoprocOption; } bool isCondCode() const { return Kind == k_CondCode; } bool isCCOut() const { return Kind == k_CCOut; } bool isITMask() const { return Kind == k_ITCondMask; } @@ -661,15 +674,18 @@ public: bool isPostIdxReg() const { return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy == ARM_AM::no_shift; } - bool isMemNoOffset() const { + bool isMemNoOffset(bool alignOK = false) const { if (!isMemory()) return false; // No offset of any kind. - return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0; + return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 && + (alignOK || Memory.Alignment == 0); + } + bool isAlignedMemory() const { + return isMemNoOffset(true); } bool isAddrMode2() const { - if (!isMemory()) - return false; + if (!isMemory() || Memory.Alignment != 0) return false; // Check for register offset. if (Memory.OffsetRegNum) return true; // Immediate offset in range [-4095, 4095]. @@ -687,8 +703,7 @@ public: return Val > -4096 && Val < 4096; } bool isAddrMode3() const { - if (!isMemory()) - return false; + if (!isMemory() || Memory.Alignment != 0) return false; // No shifts are legal for AM3. if (Memory.ShiftType != ARM_AM::no_shift) return false; // Check for register offset. @@ -711,8 +726,7 @@ public: return (Val > -256 && Val < 256) || Val == INT32_MIN; } bool isAddrMode5() const { - if (!isMemory()) - return false; + if (!isMemory() || Memory.Alignment != 0) return false; // Check for register offset. if (Memory.OffsetRegNum) return false; // Immediate offset in range [-1020, 1020] and a multiple of 4. @@ -723,23 +737,25 @@ public: } bool isMemTBB() const { if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative || - Memory.ShiftType != ARM_AM::no_shift) + Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) return false; return true; } bool isMemTBH() const { if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative || - Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1) + Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 || + Memory.Alignment != 0 ) return false; return true; } bool isMemRegOffset() const { - if (!isMemory() || !Memory.OffsetRegNum) + if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0) return false; return true; } bool isT2MemRegOffset() const { - if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative) + if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative || + Memory.Alignment != 0) return false; // Only lsl #{0, 1, 2, 3} allowed. if (Memory.ShiftType == ARM_AM::no_shift) @@ -752,14 +768,14 @@ public: // Thumb reg+reg addressing is simple. Just two registers, a base and // an offset. No shifts, negations or any other complicating factors. if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative || - Memory.ShiftType != ARM_AM::no_shift) + Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0) return false; return isARMLowRegister(Memory.BaseRegNum) && (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum)); } bool isMemThumbRIs4() const { if (!isMemory() || Memory.OffsetRegNum != 0 || - !isARMLowRegister(Memory.BaseRegNum)) + !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) return false; // Immediate offset, multiple of 4 in range [0, 124]. if (!Memory.OffsetImm) return true; @@ -768,7 +784,7 @@ public: } bool isMemThumbRIs2() const { if (!isMemory() || Memory.OffsetRegNum != 0 || - !isARMLowRegister(Memory.BaseRegNum)) + !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) return false; // Immediate offset, multiple of 4 in range [0, 62]. if (!Memory.OffsetImm) return true; @@ -777,7 +793,7 @@ public: } bool isMemThumbRIs1() const { if (!isMemory() || Memory.OffsetRegNum != 0 || - !isARMLowRegister(Memory.BaseRegNum)) + !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0) return false; // Immediate offset in range [0, 31]. if (!Memory.OffsetImm) return true; @@ -785,7 +801,8 @@ public: return Val >= 0 && Val <= 31; } bool isMemThumbSPI() const { - if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.BaseRegNum != ARM::SP) + if (!isMemory() || Memory.OffsetRegNum != 0 || + Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0) return false; // Immediate offset, multiple of 4 in range [0, 1020]. if (!Memory.OffsetImm) return true; @@ -793,7 +810,7 @@ public: return Val >= 0 && Val <= 1020 && (Val % 4) == 0; } bool isMemImm8s4Offset() const { - if (!isMemory() || Memory.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset a multiple of 4 in range [-1020, 1020]. if (!Memory.OffsetImm) return true; @@ -801,7 +818,7 @@ public: return Val >= -1020 && Val <= 1020 && (Val & 3) == 0; } bool isMemImm0_1020s4Offset() const { - if (!isMemory() || Memory.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset a multiple of 4 in range [0, 1020]. if (!Memory.OffsetImm) return true; @@ -809,7 +826,7 @@ public: return Val >= 0 && Val <= 1020 && (Val & 3) == 0; } bool isMemImm8Offset() const { - if (!isMemory() || Memory.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset in range [-255, 255]. if (!Memory.OffsetImm) return true; @@ -817,7 +834,7 @@ public: return (Val == INT32_MIN) || (Val > -256 && Val < 256); } bool isMemPosImm8Offset() const { - if (!isMemory() || Memory.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset in range [0, 255]. if (!Memory.OffsetImm) return true; @@ -825,7 +842,7 @@ public: return Val >= 0 && Val < 256; } bool isMemNegImm8Offset() const { - if (!isMemory() || Memory.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset in range [-255, -1]. if (!Memory.OffsetImm) return true; @@ -839,7 +856,7 @@ public: if (Kind == k_Immediate && !isa(getImm())) return true; - if (!isMemory() || Memory.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset in range [0, 4095]. if (!Memory.OffsetImm) return true; @@ -853,7 +870,7 @@ public: if (Kind == k_Immediate && !isa(getImm())) return true; - if (!isMemory() || Memory.OffsetRegNum != 0) + if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0) return false; // Immediate offset in range [-4095, 4095]. if (!Memory.OffsetImm) return true; @@ -868,10 +885,20 @@ public: int64_t Val = CE->getValue(); return (Val > -256 && Val < 256) || (Val == INT32_MIN); } + bool isPostIdxImm8s4() const { + if (Kind != k_Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Val = CE->getValue(); + return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) || + (Val == INT32_MIN); + } bool isMSRMask() const { return Kind == k_MSRMask; } bool isProcIFlags() const { return Kind == k_ProcIFlags; } + // NEON operands. bool isVectorIndex8() const { if (Kind != k_VectorIndex) return false; return VectorIndex.Val < 8; @@ -885,7 +912,28 @@ public: return VectorIndex.Val < 2; } + bool isNEONi8splat() const { + if (Kind != k_Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + // Must be a constant. + if (!CE) return false; + int64_t Value = CE->getValue(); + // i8 value splatted across 8 bytes. The immediate is just the 8 byte + // value. + return Value >= 0 && Value < 256; + } + bool isNEONi16splat() const { + if (Kind != k_Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + // Must be a constant. + if (!CE) return false; + int64_t Value = CE->getValue(); + // i16 value in the range [0,255] or [0x0100, 0xff00] + return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00); + } void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediates when possible. Null MCExpr = 0. @@ -909,6 +957,16 @@ public: Inst.addOperand(MCOperand::CreateImm(getCoproc())); } + void addCoprocRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(getCoproc())); + } + + void addCoprocOptionOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val)); + } + void addITMaskOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateImm(ITMask.Mask)); @@ -919,11 +977,6 @@ public: Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode()))); } - void addCoprocRegOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateImm(getCoproc())); - } - void addCCOutOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(getReg())); @@ -1123,6 +1176,12 @@ public: Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); } + void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum)); + Inst.addOperand(MCOperand::CreateImm(Memory.Alignment)); + } + void addAddrMode2Operands(MCInst &Inst, unsigned N) const { assert(N == 3 && "Invalid number of operands!"); int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0; @@ -1344,6 +1403,18 @@ public: Inst.addOperand(MCOperand::CreateImm(Imm)); } + void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *CE = dyn_cast(getImm()); + assert(CE && "non-constant post-idx-imm8s4 operand!"); + int Imm = CE->getValue(); + bool isAdd = Imm >= 0; + if (Imm == INT32_MIN) Imm = 0; + // Immediate is scaled by 4. + Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8; + Inst.addOperand(MCOperand::CreateImm(Imm)); + } + void addPostIdxRegOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); @@ -1386,6 +1457,26 @@ public: Inst.addOperand(MCOperand::CreateImm(getVectorIndex())); } + void addNEONi8splatOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + // The immediate encodes the type of constant as well as the value. + // Mask in that this is an i8 splat. + const MCConstantExpr *CE = dyn_cast(getImm()); + Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00)); + } + + void addNEONi16splatOperands(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(getImm()); + unsigned Value = CE->getValue(); + if (Value >= 256) + Value = (Value >> 8) | 0xa00; + else + Value |= 0x800; + Inst.addOperand(MCOperand::CreateImm(Value)); + } + virtual void print(raw_ostream &OS) const; static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) { @@ -1420,6 +1511,14 @@ public: return Op; } + static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) { + ARMOperand *Op = new ARMOperand(k_CoprocOption); + Op->Cop.Val = Val; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) { ARMOperand *Op = new ARMOperand(k_CCOut); Op->Reg.RegNum = RegNum; @@ -1552,6 +1651,7 @@ public: unsigned OffsetRegNum, ARM_AM::ShiftOpc ShiftType, unsigned ShiftImm, + unsigned Alignment, bool isNegative, SMLoc S, SMLoc E) { ARMOperand *Op = new ARMOperand(k_Memory); @@ -1560,6 +1660,7 @@ public: Op->Memory.OffsetRegNum = OffsetRegNum; Op->Memory.ShiftType = ShiftType; Op->Memory.ShiftImm = ShiftImm; + Op->Memory.Alignment = Alignment; Op->Memory.isNegative = isNegative; Op->StartLoc = S; Op->EndLoc = E; @@ -1633,6 +1734,9 @@ void ARMOperand::print(raw_ostream &OS) const { case k_CoprocReg: OS << ""; break; + case k_CoprocOption: + OS << ""; + break; case k_MSRMask: OS << ""; break; @@ -1765,7 +1869,6 @@ int ARMAsmParser::tryParseRegister() { Parser.Lex(); // Eat left bracket token. const MCExpr *ImmVal; - SMLoc ExprLoc = Parser.getTok().getLoc(); if (getParser().ParseExpression(ImmVal)) return MatchOperand_ParseFail; const MCConstantExpr *MCE = dyn_cast(ImmVal); @@ -1914,7 +2017,6 @@ tryParseRegisterWithWriteBack(SmallVectorImpl &Operands) { Parser.Lex(); // Eat left bracket token. const MCExpr *ImmVal; - SMLoc ExprLoc = Parser.getTok().getLoc(); if (getParser().ParseExpression(ImmVal)) return MatchOperand_ParseFail; const MCConstantExpr *MCE = dyn_cast(ImmVal); @@ -2024,7 +2126,8 @@ ARMAsmParser::OperandMatchResultTy ARMAsmParser:: parseCoprocNumOperand(SmallVectorImpl &Operands) { SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); - assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); + if (Tok.isNot(AsmToken::Identifier)) + return MatchOperand_NoMatch; int Num = MatchCoprocessorOperandName(Tok.getString(), 'p'); if (Num == -1) @@ -2042,7 +2145,8 @@ ARMAsmParser::OperandMatchResultTy ARMAsmParser:: parseCoprocRegOperand(SmallVectorImpl &Operands) { SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); - assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); + if (Tok.isNot(AsmToken::Identifier)) + return MatchOperand_NoMatch; int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c'); if (Reg == -1) @@ -2053,6 +2157,40 @@ parseCoprocRegOperand(SmallVectorImpl &Operands) { return MatchOperand_Success; } +/// parseCoprocOptionOperand - Try to parse an coprocessor option operand. +/// coproc_option : '{' imm0_255 '}' +ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +parseCoprocOptionOperand(SmallVectorImpl &Operands) { + SMLoc S = Parser.getTok().getLoc(); + + // If this isn't a '{', this isn't a coprocessor immediate operand. + if (Parser.getTok().isNot(AsmToken::LCurly)) + return MatchOperand_NoMatch; + Parser.Lex(); // Eat the '{' + + const MCExpr *Expr; + SMLoc Loc = Parser.getTok().getLoc(); + if (getParser().ParseExpression(Expr)) { + Error(Loc, "illegal expression"); + return MatchOperand_ParseFail; + } + const MCConstantExpr *CE = dyn_cast(Expr); + if (!CE || CE->getValue() < 0 || CE->getValue() > 255) { + Error(Loc, "coprocessor option must be an immediate in range [0, 255]"); + return MatchOperand_ParseFail; + } + int Val = CE->getValue(); + + // Check for and consume the closing '}' + if (Parser.getTok().isNot(AsmToken::RCurly)) + return MatchOperand_ParseFail; + SMLoc E = Parser.getTok().getLoc(); + Parser.Lex(); // Eat the '}' + + Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E)); + return MatchOperand_Success; +} + // For register list parsing, we need to map from raw GPR register numbering // to the enumeration values. The enumeration values aren't sorted by // register number due to our using "sp", "lr" and "pc" as canonical names. @@ -3021,7 +3159,7 @@ parseMemory(SmallVectorImpl &Operands) { Parser.Lex(); // Eat right bracket token. Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift, - 0, false, S, E)); + 0, 0, false, S, E)); // If there's a pre-indexing writeback marker, '!', just add it as a token // operand. It's rather odd, but syntactically valid. @@ -3036,7 +3174,54 @@ parseMemory(SmallVectorImpl &Operands) { assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!"); Parser.Lex(); // Eat the comma. - // If we have a '#' it's an immediate offset, else assume it's a register + // If we have a ':', it's an alignment specifier. + if (Parser.getTok().is(AsmToken::Colon)) { + Parser.Lex(); // Eat the ':'. + E = Parser.getTok().getLoc(); + + const MCExpr *Expr; + if (getParser().ParseExpression(Expr)) + return true; + + // The expression has to be a constant. Memory references with relocations + // don't come through here, as they use the