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("repe", "rep")
- .Case("repz", "rep")
- .Case("repnz", "repne")
- .Case("push", Is64Bit ? "pushq" : "pushl")
- .Case("pop", Is64Bit ? "popq" : "popl")
- .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
- .Case("popf", Is64Bit ? "popfq" : "popfl")
- .Case("retl", Is64Bit ? "retl" : "ret")
- .Case("retq", Is64Bit ? "ret" : "retq")
- .Case("movzx", "movzb") // FIXME: Not correct.
- .Case("fcompi", "fcomip")
- .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
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)".
NameLoc, NameLoc));
}
- // The assembler accepts this instruction with no operand as a synonym for an
- // instruction taking %st(1),%st(0). e.g. "fcompi" -> "fcompi %st(1),st(0)".
- if (Name == "fcompi" && Operands.size() == 1) {
- Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(1)"),
- NameLoc, NameLoc));
- Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(0)"),
- NameLoc, NameLoc));
- }
-
// 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" || Name == "fucompi" ||
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) {
Operands.push_back(X86Operand::CreateImm(A, NameLoc, NameLoc));
}
- // "lgdtl" is not ambiguous 32-bit mode and is the same as "lgdt".
- // "lgdtq" is not ambiguous 64-bit mode and is the same as "lgdt".
- if ((Name == "lgdtl" && Is64Bit == false) ||
- (Name == "lgdtq" && Is64Bit == true)) {
- const char *NewName = "lgdt";
- delete Operands[0];
- Operands[0] = X86Operand::CreateToken(NewName, NameLoc);
- Name = NewName;
- }
-
- // "lidtl" is not ambiguous 32-bit mode and is the same as "lidt".
- // "lidtq" is not ambiguous 64-bit mode and is the same as "lidt".
- if ((Name == "lidtl" && Is64Bit == false) ||
- (Name == "lidtq" && Is64Bit == true)) {
- const char *NewName = "lidt";
- delete Operands[0];
- Operands[0] = X86Operand::CreateToken(NewName, NameLoc);
- Name = NewName;
- }
-
- // "sgdtl" is not ambiguous 32-bit mode and is the same as "sgdt".
- // "sgdtq" is not ambiguous 64-bit mode and is the same as "sgdt".
- if ((Name == "sgdtl" && Is64Bit == false) ||
- (Name == "sgdtq" && Is64Bit == true)) {
- const char *NewName = "sgdt";
- delete Operands[0];
- Operands[0] = X86Operand::CreateToken(NewName, NameLoc);
- Name = NewName;
- }
-
- // "sidtl" is not ambiguous 32-bit mode and is the same as "sidt".
- // "sidtq" is not ambiguous 64-bit mode and is the same as "sidt".
- if ((Name == "sidtl" && Is64Bit == false) ||
- (Name == "sidtq" && Is64Bit == true)) {
- const char *NewName = "sidt";
- delete Operands[0];
- Operands[0] = X86Operand::CreateToken(NewName, NameLoc);
- Name = NewName;
- }
-
return false;
}