/// }
public:
- X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
- : TargetAsmParser(T), Parser(_Parser), TM(TM) {
+ X86ATTAsmParser(const Target &T, MCAsmParser &parser, TargetMachine &TM)
+ : TargetAsmParser(T), Parser(parser), TM(TM) {
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(
class X86_32ATTAsmParser : public X86ATTAsmParser {
public:
- X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
- : X86ATTAsmParser(T, _Parser, TM) {
+ X86_32ATTAsmParser(const Target &T, MCAsmParser &Parser, TargetMachine &TM)
+ : X86ATTAsmParser(T, Parser, TM) {
Is64Bit = false;
}
};
class X86_64ATTAsmParser : public X86ATTAsmParser {
public:
- X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
- : X86ATTAsmParser(T, _Parser, TM) {
+ X86_64ATTAsmParser(const Target &T, MCAsmParser &Parser, TargetMachine &TM)
+ : X86ATTAsmParser(T, Parser, TM) {
Is64Bit = true;
}
};
bool X86ATTAsmParser::
ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
- // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
- // represent alternative syntaxes in the .td file, without requiring
- // instruction duplication.
- StringRef PatchedName = StringSwitch<StringRef>(Name)
- .Case("sal", "shl")
- .Case("salb", "shlb")
- .Case("sall", "shll")
- .Case("salq", "shlq")
- .Case("salw", "shlw")
- .Case("repe", "rep")
- .Case("repz", "rep")
- .Case("repnz", "repne")
- .Case("iret", "iretl")
- .Case("sysret", "sysretl")
- .Case("cbw", "cbtw")
- .Case("cwd", "cwtd")
- .Case("cdq", "cltd")
- .Case("cwde", "cwtl")
- .Case("cdqe", "cltq")
- .Case("smovb", "movsb")
- .Case("smovw", "movsw")
- .Case("smovl", "movsl")
- .Case("smovq", "movsq")
- .Case("push", Is64Bit ? "pushq" : "pushl")
- .Case("pop", Is64Bit ? "popq" : "popl")
- .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
- .Case("popf", Is64Bit ? "popfq" : "popfl")
- .Case("pushfd", "pushfl")
- .Case("popfd", "popfl")
- .Case("retl", Is64Bit ? "retl" : "ret")
- .Case("retq", Is64Bit ? "ret" : "retq")
- .Case("setz", "sete") .Case("setnz", "setne")
- .Case("setc", "setb") .Case("setna", "setbe")
- .Case("setnae", "setb").Case("setnb", "setae")
- .Case("setnbe", "seta").Case("setnc", "setae")
- .Case("setng", "setle").Case("setnge", "setl")
- .Case("setnl", "setge").Case("setnle", "setg")
- .Case("setpe", "setp") .Case("setpo", "setnp")
- .Case("jz", "je") .Case("jnz", "jne")
- .Case("jc", "jb") .Case("jna", "jbe")
- .Case("jnae", "jb").Case("jnb", "jae")
- .Case("jnbe", "ja").Case("jnc", "jae")
- .Case("jng", "jle").Case("jnge", "jl")
- .Case("jnl", "jge").Case("jnle", "jg")
- .Case("jpe", "jp") .Case("jpo", "jnp")
- // Condition code aliases for 16-bit, 32-bit, 64-bit and unspec operands.
- .Case("cmovcw", "cmovbw") .Case("cmovcl", "cmovbl")
- .Case("cmovcq", "cmovbq") .Case("cmovc", "cmovb")
- .Case("cmovnaew","cmovbw") .Case("cmovnael","cmovbl")
- .Case("cmovnaeq","cmovbq") .Case("cmovnae", "cmovb")
- .Case("cmovnaw", "cmovbew").Case("cmovnal", "cmovbel")
- .Case("cmovnaq", "cmovbeq").Case("cmovna", "cmovbe")
- .Case("cmovnbw", "cmovaew").Case("cmovnbl", "cmovael")
- .Case("cmovnbq", "cmovaeq").Case("cmovnb", "cmovae")
- .Case("cmovnbew","cmovaw") .Case("cmovnbel","cmoval")
- .Case("cmovnbeq","cmovaq") .Case("cmovnbe", "cmova")
- .Case("cmovncw", "cmovaew").Case("cmovncl", "cmovael")
- .Case("cmovncq", "cmovaeq").Case("cmovnc", "cmovae")
- .Case("cmovngw", "cmovlew").Case("cmovngl", "cmovlel")
- .Case("cmovngq", "cmovleq").Case("cmovng", "cmovle")
- .Case("cmovnw", "cmovgew").Case("cmovnl", "cmovgel")
- .Case("cmovnq", "cmovgeq").Case("cmovn", "cmovge")
- .Case("cmovngw", "cmovlew").Case("cmovngl", "cmovlel")
- .Case("cmovngq", "cmovleq").Case("cmovng", "cmovle")
- .Case("cmovngew","cmovlw") .Case("cmovngel","cmovll")
- .Case("cmovngeq","cmovlq") .Case("cmovnge", "cmovl")
- .Case("cmovnlw", "cmovgew").Case("cmovnll", "cmovgel")
- .Case("cmovnlq", "cmovgeq").Case("cmovnl", "cmovge")
- .Case("cmovnlew","cmovgw") .Case("cmovnlel","cmovgl")
- .Case("cmovnleq","cmovgq") .Case("cmovnle", "cmovg")
- .Case("cmovnzw", "cmovnew").Case("cmovnzl", "cmovnel")
- .Case("cmovnzq", "cmovneq").Case("cmovnz", "cmovne")
- .Case("cmovzw", "cmovew") .Case("cmovzl", "cmovel")
- .Case("cmovzq", "cmoveq") .Case("cmovz", "cmove")
- // Floating point stack cmov aliases.
- .Case("fcmovz", "fcmove")
- .Case("fcmova", "fcmovnbe")
- .Case("fcmovnae", "fcmovb")
- .Case("fcmovna", "fcmovbe")
- .Case("fcmovae", "fcmovnb")
- .Case("fwait", "wait")
- .Case("movzx", "movzb") // FIXME: Not correct.
- .Case("fildq", "fildll")
- .Default(Name);
+ StringRef PatchedName = Name;
// FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
const MCExpr *ExtraImmOp = 0;
// Determine whether this is an instruction prefix.
bool isPrefix =
- PatchedName == "lock" || PatchedName == "rep" ||
- PatchedName == "repne";
+ Name == "lock" || Name == "rep" ||
+ Name == "repe" || Name == "repz" ||
+ Name == "repne" || Name == "repnz";
// This does the actual operand parsing. Don't parse any more if we have a
// FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>. Canonicalize to
// "shift <op>".
if ((Name.startswith("shr") || Name.startswith("sar") ||
- Name.startswith("shl")) &&
+ Name.startswith("shl") || Name.startswith("sal")) &&
Operands.size() == 3) {
X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]);
if (Op1->isImm() && isa<MCConstantExpr>(Op1->getImm()) &&
Operands[0] = X86Operand::CreateToken("sldtw", NameLoc);
}
- // The assembler accepts "xchgX <reg>, <mem>" and "xchgX <mem>, <reg>" as
- // synonyms. Our tables only have the "<reg>, <mem>" form, so if we see the
- // other operand order, swap them.
- if (Name == "xchgb" || Name == "xchgw" || Name == "xchgl" || Name == "xchgq"||
- Name == "xchg")
- if (Operands.size() == 3 &&
- static_cast<X86Operand*>(Operands[1])->isMem() &&
- static_cast<X86Operand*>(Operands[2])->isReg()) {
- std::swap(Operands[1], Operands[2]);
- }
-
- // The assembler accepts "testX <reg>, <mem>" and "testX <mem>, <reg>" as
- // synonyms. Our tables only have the "<mem>, <reg>" form, so if we see the
- // other operand order, swap them.
- if (Name == "testb" || Name == "testw" || Name == "testl" || Name == "testq"||
- Name == "test")
- if (Operands.size() == 3 &&
- static_cast<X86Operand*>(Operands[1])->isReg() &&
- static_cast<X86Operand*>(Operands[2])->isMem()) {
- std::swap(Operands[1], Operands[2]);
- }
// The assembler accepts these instructions with no operand as a synonym for
// an instruction acting on st(1). e.g. "fxch" -> "fxch %st(1)".
// The assembler accepts these instructions with two few operands as a synonym
// for taking %st(1),%st(0) or X, %st(0).
- if ((Name == "fcomi" || Name == "fucomi") && Operands.size() < 3) {
+ if ((Name == "fcomi" || Name == "fucomi" || Name == "fucompi" ||
+ Name == "fcompi" ) &&
+ Operands.size() < 3) {
if (Operands.size() == 1)
Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(1)"),
NameLoc, NameLoc));
}
// The assembler accepts various amounts of brokenness for fnstsw.
- if (Name == "fnstsw") {
+ if (Name == "fnstsw" || Name == "fnstsww") {
if (Operands.size() == 2 &&
static_cast<X86Operand*>(Operands[1])->isReg()) {
// "fnstsw al" and "fnstsw eax" -> "fnstw"
NameLoc, NameLoc));
}
- // jmp $42,$5 -> ljmp, similarly for call.
- if ((Name.startswith("call") || Name.startswith("jmp")) &&
- Operands.size() == 3 &&
- static_cast<X86Operand*>(Operands[1])->isImm() &&
- static_cast<X86Operand*>(Operands[2])->isImm()) {
- const char *NewOpName = StringSwitch<const char *>(Name)
- .Case("jmp", "ljmp")
- .Case("jmpw", "ljmpw")
- .Case("jmpl", "ljmpl")
- .Case("jmpq", "ljmpq")
- .Case("call", "lcall")
- .Case("callw", "lcallw")
- .Case("calll", "lcalll")
- .Case("callq", "lcallq")
- .Default(0);
- if (NewOpName) {
- delete Operands[0];
- Operands[0] = X86Operand::CreateToken(NewOpName, NameLoc);
- Name = NewOpName;
- }
- }
-
- // lcall and ljmp -> lcalll and ljmpl
- if ((Name == "lcall" || Name == "ljmp") && Operands.size() == 3) {
- delete Operands[0];
- Operands[0] = X86Operand::CreateToken(Name == "lcall" ? "lcalll" : "ljmpl",
- NameLoc);
- }
-
- // call foo is not ambiguous with callw.
- if (Name == "call" && Operands.size() == 2) {
- const char *NewName = Is64Bit ? "callq" : "calll";
- delete Operands[0];
- Operands[0] = X86Operand::CreateToken(NewName, NameLoc);
- Name = NewName;
- }
-
- // movsd -> movsl (when no operands are specified).
- if (Name == "movsd" && Operands.size() == 1) {
- delete Operands[0];
- Operands[0] = X86Operand::CreateToken("movsl", NameLoc);
- }
-
// fstp <mem> -> fstps <mem>. Without this, we'll default to fstpl due to
// suffix searching.
if (Name == "fstp" && Operands.size() == 2 &&
Operands[0] = X86Operand::CreateToken("fstps", NameLoc);
}
-
- // "clr <reg>" -> "xor <reg>, <reg>".
- if ((Name == "clrb" || Name == "clrw" || Name == "clrl" || Name == "clrq" ||
- Name == "clr") && Operands.size() == 2 &&
- static_cast<X86Operand*>(Operands[1])->isReg()) {
- unsigned RegNo = static_cast<X86Operand*>(Operands[1])->getReg();
- Operands.push_back(X86Operand::CreateReg(RegNo, NameLoc, NameLoc));
- delete Operands[0];
- Operands[0] = X86Operand::CreateToken("xor", NameLoc);
- }
-
// FIXME: Hack to handle recognize "aa[dm]" -> "aa[dm] $0xA".
if ((Name.startswith("aad") || Name.startswith("aam")) &&
Operands.size() == 1) {
return false;
}
-bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
- StringRef IDVal = DirectiveID.getIdentifier();
- if (IDVal == ".word")
- return ParseDirectiveWord(2, DirectiveID.getLoc());
- return true;
-}
-
-/// ParseDirectiveWord
-/// ::= .word [ expression (, expression)* ]
-bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- for (;;) {
- const MCExpr *Value;
- if (getParser().ParseExpression(Value))
- return true;
-
- getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
-
- if (getLexer().is(AsmToken::EndOfStatement))
- break;
-
- // FIXME: Improve diagnostic.
- if (getLexer().isNot(AsmToken::Comma))
- return Error(L, "unexpected token in directive");
- Parser.Lex();
- }
- }
-
- Parser.Lex();
- return false;
-}
-
-
bool X86ATTAsmParser::
MatchAndEmitInstruction(SMLoc IDLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
// First, handle aliases that expand to multiple instructions.
// FIXME: This should be replaced with a real .td file alias mechanism.
if (Op->getToken() == "fstsw" || Op->getToken() == "fstcw" ||
+ Op->getToken() == "fstsww" || Op->getToken() == "fstcww" ||
Op->getToken() == "finit" || Op->getToken() == "fsave" ||
- Op->getToken() == "fstenv") {
+ Op->getToken() == "fstenv" || Op->getToken() == "fclex") {
MCInst Inst;
Inst.setOpcode(X86::WAIT);
Out.EmitInstruction(Inst);
const char *Repl =
StringSwitch<const char*>(Op->getToken())
- .Case("finit", "fninit")
- .Case("fsave", "fnsave")
- .Case("fstcw", "fnstcw")
+ .Case("finit", "fninit")
+ .Case("fsave", "fnsave")
+ .Case("fstcw", "fnstcw")
+ .Case("fstcww", "fnstcw")
.Case("fstenv", "fnstenv")
- .Case("fstsw", "fnstsw")
+ .Case("fstsw", "fnstsw")
+ .Case("fstsww", "fnstsw")
+ .Case("fclex", "fnclex")
.Default(0);
assert(Repl && "Unknown wait-prefixed instruction");
delete Operands[0];
}
+bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
+ StringRef IDVal = DirectiveID.getIdentifier();
+ if (IDVal == ".word")
+ return ParseDirectiveWord(2, DirectiveID.getLoc());
+ return true;
+}
+
+/// ParseDirectiveWord
+/// ::= .word [ expression (, expression)* ]
+bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ for (;;) {
+ const MCExpr *Value;
+ if (getParser().ParseExpression(Value))
+ return true;
+
+ getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
+
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ // FIXME: Improve diagnostic.
+ if (getLexer().isNot(AsmToken::Comma))
+ return Error(L, "unexpected token in directive");
+ Parser.Lex();
+ }
+ }
+
+ Parser.Lex();
+ return false;
+}
+
+
+
+
extern "C" void LLVMInitializeX86AsmLexer();
// Force static initialization.