diff options
Diffstat (limited to 'lib/Target/X86/AsmParser/X86AsmParser.cpp')
-rw-r--r-- | lib/Target/X86/AsmParser/X86AsmParser.cpp | 620 |
1 files changed, 571 insertions, 49 deletions
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index f4639a3..d91830f 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -31,10 +31,9 @@ using namespace llvm; namespace { struct X86Operand; -class X86ATTAsmParser : public MCTargetAsmParser { +class X86AsmParser : public MCTargetAsmParser { MCSubtargetInfo &STI; MCAsmParser &Parser; - private: MCAsmParser &getParser() const { return Parser; } @@ -45,12 +44,24 @@ private: return Parser.Error(L, Msg, Ranges); } + X86Operand *ErrorOperand(SMLoc Loc, StringRef Msg) { + Error(Loc, Msg); + return 0; + } + X86Operand *ParseOperand(); + X86Operand *ParseATTOperand(); + X86Operand *ParseIntelOperand(); + X86Operand *ParseIntelMemOperand(); + X86Operand *ParseIntelBracExpression(unsigned SegReg, unsigned Size); X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc); bool ParseDirectiveWord(unsigned Size, SMLoc L); bool ParseDirectiveCode(StringRef IDVal, SMLoc L); + bool processInstruction(MCInst &Inst, + const SmallVectorImpl<MCParsedAsmOperand*> &Ops); + bool MatchAndEmitInstruction(SMLoc IDLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCStreamer &Out); @@ -81,7 +92,7 @@ private: /// } public: - X86ATTAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser) + X86AsmParser(MCSubtargetInfo &sti, MCAsmParser &parser) : MCTargetAsmParser(), STI(sti), Parser(parser) { // Initialize the set of available features. @@ -93,6 +104,10 @@ public: SmallVectorImpl<MCParsedAsmOperand*> &Operands); virtual bool ParseDirective(AsmToken DirectiveID); + + bool isParsingIntelSyntax() { + return getParser().getAssemblerDialect(); + } }; } // end anonymous namespace @@ -103,6 +118,31 @@ static unsigned MatchRegisterName(StringRef Name); /// } +static bool isImmSExti16i8Value(uint64_t Value) { + return (( Value <= 0x000000000000007FULL)|| + (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)|| + (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL)); +} + +static bool isImmSExti32i8Value(uint64_t Value) { + return (( Value <= 0x000000000000007FULL)|| + (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)|| + (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL)); +} + +static bool isImmZExtu32u8Value(uint64_t Value) { + return (Value <= 0x00000000000000FFULL); +} + +static bool isImmSExti64i8Value(uint64_t Value) { + return (( Value <= 0x000000000000007FULL)|| + (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL)); +} + +static bool isImmSExti64i32Value(uint64_t Value) { + return (( Value <= 0x000000007FFFFFFFULL)|| + (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL)); +} namespace { /// X86Operand - Instances of this class represent a parsed X86 machine @@ -137,6 +177,7 @@ struct X86Operand : public MCParsedAsmOperand { unsigned BaseReg; unsigned IndexReg; unsigned Scale; + unsigned Size; } Mem; }; @@ -209,10 +250,7 @@ struct X86Operand : public MCParsedAsmOperand { // Otherwise, check the value is in a range that makes sense for this // extension. - uint64_t Value = CE->getValue(); - return (( Value <= 0x000000000000007FULL)|| - (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)|| - (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL)); + return isImmSExti16i8Value(CE->getValue()); } bool isImmSExti32i8() const { if (!isImm()) @@ -226,10 +264,7 @@ struct X86Operand : public MCParsedAsmOperand { // Otherwise, check the value is in a range that makes sense for this // extension. - uint64_t Value = CE->getValue(); - return (( Value <= 0x000000000000007FULL)|| - (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)|| - (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL)); + return isImmSExti32i8Value(CE->getValue()); } bool isImmZExtu32u8() const { if (!isImm()) @@ -243,8 +278,7 @@ struct X86Operand : public MCParsedAsmOperand { // Otherwise, check the value is in a range that makes sense for this // extension. - uint64_t Value = CE->getValue(); - return (Value <= 0x00000000000000FFULL); + return isImmZExtu32u8Value(CE->getValue()); } bool isImmSExti64i8() const { if (!isImm()) @@ -258,9 +292,7 @@ struct X86Operand : public MCParsedAsmOperand { // Otherwise, check the value is in a range that makes sense for this // extension. - uint64_t Value = CE->getValue(); - return (( Value <= 0x000000000000007FULL)|| - (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL)); + return isImmSExti64i8Value(CE->getValue()); } bool isImmSExti64i32() const { if (!isImm()) @@ -274,12 +306,31 @@ struct X86Operand : public MCParsedAsmOperand { // Otherwise, check the value is in a range that makes sense for this // extension. - uint64_t Value = CE->getValue(); - return (( Value <= 0x000000007FFFFFFFULL)|| - (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL)); + return isImmSExti64i32Value(CE->getValue()); } bool isMem() const { return Kind == Memory; } + bool isMem8() const { + return Kind == Memory && (!Mem.Size || Mem.Size == 8); + } + bool isMem16() const { + return Kind == Memory && (!Mem.Size || Mem.Size == 16); + } + bool isMem32() const { + return Kind == Memory && (!Mem.Size || Mem.Size == 32); + } + bool isMem64() const { + return Kind == Memory && (!Mem.Size || Mem.Size == 64); + } + bool isMem80() const { + return Kind == Memory && (!Mem.Size || Mem.Size == 80); + } + bool isMem128() const { + return Kind == Memory && (!Mem.Size || Mem.Size == 128); + } + bool isMem256() const { + return Kind == Memory && (!Mem.Size || Mem.Size == 256); + } bool isAbsMem() const { return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && @@ -306,6 +357,28 @@ struct X86Operand : public MCParsedAsmOperand { addExpr(Inst, getImm()); } + void addMem8Operands(MCInst &Inst, unsigned N) const { + addMemOperands(Inst, N); + } + void addMem16Operands(MCInst &Inst, unsigned N) const { + addMemOperands(Inst, N); + } + void addMem32Operands(MCInst &Inst, unsigned N) const { + addMemOperands(Inst, N); + } + void addMem64Operands(MCInst &Inst, unsigned N) const { + addMemOperands(Inst, N); + } + void addMem80Operands(MCInst &Inst, unsigned N) const { + addMemOperands(Inst, N); + } + void addMem128Operands(MCInst &Inst, unsigned N) const { + addMemOperands(Inst, N); + } + void addMem256Operands(MCInst &Inst, unsigned N) const { + addMemOperands(Inst, N); + } + void addMemOperands(MCInst &Inst, unsigned N) const { assert((N == 5) && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(getMemBaseReg())); @@ -317,7 +390,11 @@ struct X86Operand : public MCParsedAsmOperand { void addAbsMemOperands(MCInst &Inst, unsigned N) const { assert((N == 1) && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateExpr(getMemDisp())); + // Add as immediates when possible. + if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp())) + Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + else + Inst.addOperand(MCOperand::CreateExpr(getMemDisp())); } static X86Operand *CreateToken(StringRef Str, SMLoc Loc) { @@ -342,20 +419,22 @@ struct X86Operand : public MCParsedAsmOperand { /// Create an absolute memory operand. static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc, - SMLoc EndLoc) { + SMLoc EndLoc, unsigned Size = 0) { X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc); Res->Mem.SegReg = 0; Res->Mem.Disp = Disp; Res->Mem.BaseReg = 0; Res->Mem.IndexReg = 0; Res->Mem.Scale = 1; + Res->Mem.Size = Size; return Res; } /// Create a generalized memory operand. static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg, - unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) { + unsigned Scale, SMLoc StartLoc, SMLoc EndLoc, + unsigned Size = 0) { // We should never just have a displacement, that should be parsed as an // absolute memory operand. assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!"); @@ -369,13 +448,14 @@ struct X86Operand : public MCParsedAsmOperand { Res->Mem.BaseReg = BaseReg; Res->Mem.IndexReg = IndexReg; Res->Mem.Scale = Scale; + Res->Mem.Size = Size; return Res; } }; } // end anonymous namespace. -bool X86ATTAsmParser::isSrcOp(X86Operand &Op) { +bool X86AsmParser::isSrcOp(X86Operand &Op) { unsigned basereg = is64BitMode() ? X86::RSI : X86::ESI; return (Op.isMem() && @@ -385,7 +465,7 @@ bool X86ATTAsmParser::isSrcOp(X86Operand &Op) { Op.Mem.BaseReg == basereg && Op.Mem.IndexReg == 0); } -bool X86ATTAsmParser::isDstOp(X86Operand &Op) { +bool X86AsmParser::isDstOp(X86Operand &Op) { unsigned basereg = is64BitMode() ? X86::RDI : X86::EDI; return Op.isMem() && Op.Mem.SegReg == X86::ES && @@ -394,18 +474,22 @@ bool X86ATTAsmParser::isDstOp(X86Operand &Op) { Op.Mem.BaseReg == basereg && Op.Mem.IndexReg == 0; } -bool X86ATTAsmParser::ParseRegister(unsigned &RegNo, - SMLoc &StartLoc, SMLoc &EndLoc) { +bool X86AsmParser::ParseRegister(unsigned &RegNo, + SMLoc &StartLoc, SMLoc &EndLoc) { RegNo = 0; - const AsmToken &TokPercent = Parser.getTok(); - assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!"); - StartLoc = TokPercent.getLoc(); - Parser.Lex(); // Eat percent token. + if (!isParsingIntelSyntax()) { + const AsmToken &TokPercent = Parser.getTok(); + assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!"); + StartLoc = TokPercent.getLoc(); + Parser.Lex(); // Eat percent token. + } const AsmToken &Tok = Parser.getTok(); - if (Tok.isNot(AsmToken::Identifier)) + if (Tok.isNot(AsmToken::Identifier)) { + if (isParsingIntelSyntax()) return true; return Error(StartLoc, "invalid register name", SMRange(StartLoc, Tok.getEndLoc())); + } RegNo = MatchRegisterName(Tok.getString()); @@ -485,16 +569,182 @@ bool X86ATTAsmParser::ParseRegister(unsigned &RegNo, } } - if (RegNo == 0) + if (RegNo == 0) { + if (isParsingIntelSyntax()) return true; return Error(StartLoc, "invalid register name", SMRange(StartLoc, Tok.getEndLoc())); + } EndLoc = Tok.getEndLoc(); Parser.Lex(); // Eat identifier token. return false; } -X86Operand *X86ATTAsmParser::ParseOperand() { +X86Operand *X86AsmParser::ParseOperand() { + if (isParsingIntelSyntax()) + return ParseIntelOperand(); + return ParseATTOperand(); +} + +/// getIntelMemOperandSize - Return intel memory operand size. +static unsigned getIntelMemOperandSize(StringRef OpStr) { + unsigned Size = 0; + if (OpStr == "BYTE") Size = 8; + if (OpStr == "WORD") Size = 16; + if (OpStr == "DWORD") Size = 32; + if (OpStr == "QWORD") Size = 64; + if (OpStr == "XWORD") Size = 80; + if (OpStr == "XMMWORD") Size = 128; + if (OpStr == "YMMWORD") Size = 256; + return Size; +} + +X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, + unsigned Size) { + unsigned BaseReg = 0, IndexReg = 0, Scale = 1; + SMLoc Start = Parser.getTok().getLoc(), End; + + const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext()); + // Parse [ BaseReg + Scale*IndexReg + Disp ] or [ symbol ] + + // Eat '[' + if (getLexer().isNot(AsmToken::LBrac)) + return ErrorOperand(Start, "Expected '[' token!"); + Parser.Lex(); + + if (getLexer().is(AsmToken::Identifier)) { + // Parse BaseReg + if (ParseRegister(BaseReg, Start, End)) { + // Handle '[' 'symbol' ']' + if (getParser().ParseExpression(Disp, End)) return 0; + if (getLexer().isNot(AsmToken::RBrac)) + return ErrorOperand(Start, "Expected ']' token!"); + Parser.Lex(); + return X86Operand::CreateMem(Disp, Start, End, Size); + } + } else if (getLexer().is(AsmToken::Integer)) { + int64_t Val = Parser.getTok().getIntVal(); + Parser.Lex(); + SMLoc Loc = Parser.getTok().getLoc(); + if (getLexer().is(AsmToken::RBrac)) { + // Handle '[' number ']' + Parser.Lex(); + const MCExpr *Disp = MCConstantExpr::Create(Val, getContext()); + if (SegReg) + return X86Operand::CreateMem(SegReg, Disp, 0, 0, Scale, + Start, End, Size); + return X86Operand::CreateMem(Disp, Start, End, Size); + } else if (getLexer().is(AsmToken::Star)) { + // Handle '[' Scale*IndexReg ']' + Parser.Lex(); + SMLoc IdxRegLoc = Parser.getTok().getLoc(); + if (ParseRegister(IndexReg, IdxRegLoc, End)) + return ErrorOperand(IdxRegLoc, "Expected register"); + Scale = Val; + } else + return ErrorOperand(Loc, "Unepxeted token"); + } + + if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) { + bool isPlus = getLexer().is(AsmToken::Plus); + Parser.Lex(); + SMLoc PlusLoc = Parser.getTok().getLoc(); + if (getLexer().is(AsmToken::Integer)) { + int64_t Val = Parser.getTok().getIntVal(); + Parser.Lex(); + if (getLexer().is(AsmToken::Star)) { + Parser.Lex(); + SMLoc IdxRegLoc = Parser.getTok().getLoc(); + if (ParseRegister(IndexReg, IdxRegLoc, End)) + return ErrorOperand(IdxRegLoc, "Expected register"); + Scale = Val; + } else if (getLexer().is(AsmToken::RBrac)) { + const MCExpr *ValExpr = MCConstantExpr::Create(Val, getContext()); + Disp = isPlus ? ValExpr : MCConstantExpr::Create(0-Val, getContext()); + } else + return ErrorOperand(PlusLoc, "unexpected token after +"); + } else if (getLexer().is(AsmToken::Identifier)) { + // This could be an index register or a displacement expression. + End = Parser.getTok().getLoc(); + if (!IndexReg) + ParseRegister(IndexReg, Start, End); + else if (getParser().ParseExpression(Disp, End)) return 0; + } + } + + if (getLexer().isNot(AsmToken::RBrac)) + if (getParser().ParseExpression(Disp, End)) return 0; + + End = Parser.getTok().getLoc(); + if (getLexer().isNot(AsmToken::RBrac)) + return ErrorOperand(End, "expected ']' token!"); + Parser.Lex(); + End = Parser.getTok().getLoc(); + + // handle [-42] + if (!BaseReg && !IndexReg) + return X86Operand::CreateMem(Disp, Start, End, Size); + + return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, + Start, End, Size); +} + +/// ParseIntelMemOperand - Parse intel style memory operand. +X86Operand *X86AsmParser::ParseIntelMemOperand() { + const AsmToken &Tok = Parser.getTok(); + SMLoc Start = Parser.getTok().getLoc(), End; + unsigned SegReg = 0; + + unsigned Size = getIntelMemOperandSize(Tok.getString()); + if (Size) { + Parser.Lex(); + assert (Tok.getString() == "PTR" && "Unexpected token!"); + Parser.Lex(); + } + + if (getLexer().is(AsmToken::LBrac)) + return ParseIntelBracExpression(SegReg, Size); + + if (!ParseRegister(SegReg, Start, End)) { + // Handel SegReg : [ ... ] + if (getLexer().isNot(AsmToken::Colon)) + return ErrorOperand(Start, "Expected ':' token!"); + Parser.Lex(); // Eat : + if (getLexer().isNot(AsmToken::LBrac)) + return ErrorOperand(Start, "Expected '[' token!"); + return ParseIntelBracExpression(SegReg, Size); + } + + const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext()); + if (getParser().ParseExpression(Disp, End)) return 0; + return X86Operand::CreateMem(Disp, Start, End, Size); +} + +X86Operand *X86AsmParser::ParseIntelOperand() { + SMLoc Start = Parser.getTok().getLoc(), End; + + // immediate. + if (getLexer().is(AsmToken::Integer) || getLexer().is(AsmToken::Real) || + getLexer().is(AsmToken::Minus)) { + const MCExpr *Val; + if (!getParser().ParseExpression(Val, End)) { + End = Parser.getTok().getLoc(); + return X86Operand::CreateImm(Val, Start, End); + } + } + + // register + unsigned RegNo = 0; + if (!ParseRegister(RegNo, Start, End)) { + End = Parser.getTok().getLoc(); + return X86Operand::CreateReg(RegNo, Start, End); + } + + // mem operand + return ParseIntelMemOperand(); +} + +X86Operand *X86AsmParser::ParseATTOperand() { switch (getLexer().getKind()) { default: // Parse a memory operand with no segment register. @@ -533,7 +783,7 @@ X86Operand *X86ATTAsmParser::ParseOperand() { /// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix /// has already been parsed if present. -X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) { +X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) { // We have to disambiguate a parenthesized expression "(4+5)" from the start // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The @@ -664,7 +914,7 @@ X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) { MemStart, MemEnd); } -bool X86ATTAsmParser:: +bool X86AsmParser:: ParseInstruction(StringRef Name, SMLoc NameLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands) { StringRef PatchedName = Name; @@ -734,10 +984,9 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc)); - if (ExtraImmOp) + if (ExtraImmOp && !isParsingIntelSyntax()) Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc)); - // Determine whether this is an instruction prefix. bool isPrefix = Name == "lock" || Name == "rep" || @@ -791,6 +1040,9 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, else if (isPrefix && getLexer().is(AsmToken::Slash)) Parser.Lex(); // Consume the prefix separator Slash + if (ExtraImmOp && isParsingIntelSyntax()) + Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc)); + // This is a terrible hack to handle "out[bwl]? %al, (%dx)" -> // "outb %al, %dx". Out doesn't take a memory form, but this is a widely // documented form in various unofficial manuals, so a lot of code uses it. @@ -926,11 +1178,21 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, Name.startswith("rcl") || Name.startswith("rcr") || Name.startswith("rol") || Name.startswith("ror")) && Operands.size() == 3) { - X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]); - if (Op1->isImm() && isa<MCConstantExpr>(Op1->getImm()) && - cast<MCConstantExpr>(Op1->getImm())->getValue() == 1) { - delete Operands[1]; - Operands.erase(Operands.begin() + 1); + if (isParsingIntelSyntax()) { + // Intel syntax + X86Operand *Op1 = static_cast<X86Operand*>(Operands[2]); + if (Op1->isImm() && isa<MCConstantExpr>(Op1->getImm()) && + cast<MCConstantExpr>(Op1->getImm())->getValue() == 1) { + delete Operands[2]; + Operands.pop_back(); + } + } else { + X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]); + if (Op1->isImm() && isa<MCConstantExpr>(Op1->getImm()) && + cast<MCConstantExpr>(Op1->getImm())->getValue() == 1) { + delete Operands[1]; + Operands.erase(Operands.begin() + 1); + } } } @@ -949,7 +1211,246 @@ ParseInstruction(StringRef Name, SMLoc NameLoc, return false; } -bool X86ATTAsmParser:: +bool X86AsmParser:: +processInstruction(MCInst &Inst, + const SmallVectorImpl<MCParsedAsmOperand*> &Ops) { + switch (Inst.getOpcode()) { + default: return false; + case X86::AND16i16: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti16i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::AND16ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::AX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::AX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::AND32i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti32i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::AND32ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::EAX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::EAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::AND64i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti64i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::AND64ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::RAX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::RAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::XOR16i16: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti16i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::XOR16ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::AX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::AX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::XOR32i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti32i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::XOR32ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::EAX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::EAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::XOR64i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti64i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::XOR64ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::RAX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::RAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::OR16i16: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti16i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::OR16ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::AX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::AX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::OR32i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti32i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::OR32ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::EAX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::EAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::OR64i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti64i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::OR64ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::RAX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::RAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::CMP16i16: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti16i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::CMP16ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::AX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::CMP32i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti32i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::CMP32ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::EAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::CMP64i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti64i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::CMP64ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::RAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::ADD16i16: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti16i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::ADD16ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::AX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::AX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::ADD32i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti32i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::ADD32ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::EAX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::EAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::ADD64i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti64i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::ADD64ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::RAX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::RAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::SUB16i16: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti16i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::SUB16ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::AX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::AX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::SUB32i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti32i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::SUB32ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::EAX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::EAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + case X86::SUB64i32: { + if (!Inst.getOperand(0).isImm() || + !isImmSExti64i8Value(Inst.getOperand(0).getImm())) + return false; + + MCInst TmpInst; + TmpInst.setOpcode(X86::SUB64ri8); + TmpInst.addOperand(MCOperand::CreateReg(X86::RAX)); + TmpInst.addOperand(MCOperand::CreateReg(X86::RAX)); + TmpInst.addOperand(Inst.getOperand(0)); + Inst = TmpInst; + return true; + } + } +} + +bool X86AsmParser:: MatchAndEmitInstruction(SMLoc IDLoc, SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCStreamer &Out) { @@ -967,6 +1468,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, Op->getToken() == "fstenv" || Op->getToken() == "fclex") { MCInst Inst; Inst.setOpcode(X86::WAIT); + Inst.setLoc(IDLoc); Out.EmitInstruction(Inst); const char *Repl = @@ -990,9 +1492,17 @@ MatchAndEmitInstruction(SMLoc IDLoc, MCInst Inst; // First, try a direct match. - switch (MatchInstructionImpl(Operands, Inst, OrigErrorInfo)) { + switch (MatchInstructionImpl(Operands, Inst, OrigErrorInfo, + isParsingIntelSyntax())) { default: break; case Match_Success: + // Some instructions need post-processing to, for example, tweak which + // encoding is selected. Loop on it while changes happen so the + // individual transformations can chain off each other. + while (processInstruction(Inst, Operands)) + ; + + Inst.setLoc(IDLoc); Out.EmitInstruction(Inst); return false; case Match_MissingFeature: @@ -1050,6 +1560,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, (Match1 == Match_Success) + (Match2 == Match_Success) + (Match3 == Match_Success) + (Match4 == Match_Success); if (NumSuccessfulMatches == 1) { + Inst.setLoc(IDLoc); Out.EmitInstruction(Inst); return false; } @@ -1130,18 +1641,29 @@ MatchAndEmitInstruction(SMLoc IDLoc, } -bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) { +bool X86AsmParser::ParseDirective(AsmToken DirectiveID) { StringRef IDVal = DirectiveID.getIdentifier(); if (IDVal == ".word") return ParseDirectiveWord(2, DirectiveID.getLoc()); else if (IDVal.startswith(".code")) return ParseDirectiveCode(IDVal, DirectiveID.getLoc()); + else if (IDVal.startswith(".intel_syntax")) { + getParser().setAssemblerDialect(1); + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if(Parser.getTok().getString() == "noprefix") { + // FIXME : Handle noprefix + Parser.Lex(); + } else + return true; + } + return false; + } return true; } /// ParseDirectiveWord /// ::= .word [ expression (, expression)* ] -bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { +bool X86AsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { if (getLexer().isNot(AsmToken::EndOfStatement)) { for (;;) { const MCExpr *Value; @@ -1166,7 +1688,7 @@ bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) { /// ParseDirectiveCode /// ::= .code32 | .code64 -bool X86ATTAsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) { +bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) { if (IDVal == ".code32") { Parser.Lex(); if (is64BitMode()) { @@ -1191,8 +1713,8 @@ extern "C" void LLVMInitializeX86AsmLexer(); // Force static initialization. extern "C" void LLVMInitializeX86AsmParser() { - RegisterMCAsmParser<X86ATTAsmParser> X(TheX86_32Target); - RegisterMCAsmParser<X86ATTAsmParser> Y(TheX86_64Target); + RegisterMCAsmParser<X86AsmParser> X(TheX86_32Target); + RegisterMCAsmParser<X86AsmParser> Y(TheX86_64Target); LLVMInitializeX86AsmLexer(); } |