SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
StringRef PatchedName = Name;
+ // FIXME: Hack to recognize setneb as setne.
+ if (PatchedName.startswith("set") && PatchedName.endswith("b") &&
+ PatchedName != "setb" && PatchedName != "setnb")
+ PatchedName = PatchedName.substr(0, Name.size()-1);
+
// FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
const MCExpr *ExtraImmOp = 0;
if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
bool isPrefix =
Name == "lock" || Name == "rep" ||
Name == "repe" || Name == "repz" ||
- Name == "repne" || Name == "repnz";
+ Name == "repne" || Name == "repnz" ||
+ Name == "rex64" || Name == "data16";
// This does the actual operand parsing. Don't parse any more if we have a
}
if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ SMLoc Loc = getLexer().getLoc();
Parser.EatToEndOfStatement();
- return TokError("unexpected token in argument list");
+ return Error(Loc, "unexpected token in argument list");
}
}
if (getLexer().is(AsmToken::EndOfStatement))
Parser.Lex(); // Consume the EndOfStatement
- // Hack to allow 'movq <largeimm>, <reg>' as an alias for movabsq.
- if ((Name == "movq" || Name == "mov") && Operands.size() == 3 &&
- static_cast<X86Operand*>(Operands[2])->isReg() &&
- static_cast<X86Operand*>(Operands[1])->isImm() &&
- !static_cast<X86Operand*>(Operands[1])->isImmSExti64i32()) {
- delete Operands[0];
- Operands[0] = X86Operand::CreateToken("movabsq", NameLoc);
- }
-
- // 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("sal")) &&
- 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);
- }
- }
-
- // FIXME: Hack to handle recognize "rc[lr] <op>" -> "rcl $1, <op>".
- if ((Name.startswith("rcl") || Name.startswith("rcr")) &&
- Operands.size() == 2) {
- const MCExpr *One = MCConstantExpr::Create(1, getParser().getContext());
- Operands.push_back(X86Operand::CreateImm(One, NameLoc, NameLoc));
- std::swap(Operands[1], Operands[2]);
- }
-
- // FIXME: Hack to handle recognize "sh[lr]d op,op" -> "shld $1, op,op".
- if ((Name.startswith("shld") || Name.startswith("shrd")) &&
- Operands.size() == 3) {
- const MCExpr *One = MCConstantExpr::Create(1, getParser().getContext());
- Operands.insert(Operands.begin()+1,
- X86Operand::CreateImm(One, NameLoc, NameLoc));
- }
-
-
- // FIXME: Hack to handle recognize "in[bwl] <op>". Canonicalize it to
- // "inb <op>, %al".
- if ((Name == "inb" || Name == "inw" || Name == "inl") &&
- Operands.size() == 2) {
- unsigned Reg;
- if (Name[2] == 'b')
- Reg = MatchRegisterName("al");
- else if (Name[2] == 'w')
- Reg = MatchRegisterName("ax");
- else
- Reg = MatchRegisterName("eax");
- SMLoc Loc = Operands.back()->getEndLoc();
- Operands.push_back(X86Operand::CreateReg(Reg, Loc, Loc));
- }
-
- // FIXME: Hack to handle recognize "out[bwl] <op>". Canonicalize it to
- // "outb %al, <op>".
- if ((Name == "outb" || Name == "outw" || Name == "outl") &&
- Operands.size() == 2) {
- unsigned Reg;
- if (Name[3] == 'b')
- Reg = MatchRegisterName("al");
- else if (Name[3] == 'w')
- Reg = MatchRegisterName("ax");
- else
- Reg = MatchRegisterName("eax");
- SMLoc Loc = Operands.back()->getEndLoc();
- Operands.push_back(X86Operand::CreateReg(Reg, Loc, Loc));
- std::swap(Operands[1], Operands[2]);
- }
-
- // FIXME: Hack to handle "out[bwl]? %al, (%dx)" -> "outb %al, %dx".
+ // 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.
if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") &&
Operands.size() == 3) {
X86Operand &Op = *(X86Operand*)Operands.back();
delete &Op;
}
}
-
- // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
- // "f{mul*,add*,sub*,div*} $op"
- if ((Name.startswith("fmul") || Name.startswith("fadd") ||
- Name.startswith("fsub") || Name.startswith("fdiv")) &&
- Operands.size() == 3 &&
- static_cast<X86Operand*>(Operands[2])->isReg() &&
- static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
- delete Operands[2];
- Operands.erase(Operands.begin() + 2);
- }
-
- // FIXME: Hack to handle "f{mulp,addp} st(0), $op" the same as
- // "f{mulp,addp} $op", since they commute. We also allow fdivrp/fsubrp even
- // though they don't commute, solely because gas does support this.
- if ((Name=="fmulp" || Name=="faddp" || Name=="fsubrp" || Name=="fdivrp") &&
- Operands.size() == 3 &&
- static_cast<X86Operand*>(Operands[1])->isReg() &&
- static_cast<X86Operand*>(Operands[1])->getReg() == X86::ST0) {
- delete Operands[1];
- Operands.erase(Operands.begin() + 1);
- }
-
- // FIXME: Hack to handle "imul <imm>, B" which is an alias for "imul <imm>, B,
- // B".
- if (Name.startswith("imul") && Operands.size() == 3 &&
- static_cast<X86Operand*>(Operands[1])->isImm() &&
- static_cast<X86Operand*>(Operands.back())->isReg()) {
- X86Operand *Op = static_cast<X86Operand*>(Operands.back());
- Operands.push_back(X86Operand::CreateReg(Op->getReg(), Op->getStartLoc(),
- Op->getEndLoc()));
- }
-
- // 'sldt <mem>' can be encoded with either sldtw or sldtq with the same
- // effect (both store to a 16-bit mem). Force to sldtw to avoid ambiguity
- // errors, since its encoding is the most compact.
- if (Name == "sldt" && Operands.size() == 2 &&
- static_cast<X86Operand*>(Operands[1])->isMem()) {
- delete Operands[0];
- 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)".
- if ((Name == "fxch" || Name == "fucom" || Name == "fucomp" ||
- Name == "faddp" || Name == "fsubp" || Name == "fsubrp" ||
- Name == "fmulp" || Name == "fdivp" || Name == "fdivrp") &&
- Operands.size() == 1) {
- Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(1)"),
- 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" ||
- Name == "fcompi" ) &&
- Operands.size() < 3) {
- if (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 various amounts of brokenness for fnstsw.
- if (Name == "fnstsw" || Name == "fnstsww") {
- if (Operands.size() == 2 &&
- static_cast<X86Operand*>(Operands[1])->isReg()) {
- // "fnstsw al" and "fnstsw eax" -> "fnstw"
- unsigned Reg = static_cast<X86Operand*>(Operands[1])->Reg.RegNo;
- if (Reg == MatchRegisterName("eax") ||
- Reg == MatchRegisterName("al")) {
- delete Operands[1];
- Operands.pop_back();
- }
- }
-
- // "fnstw" -> "fnstw %ax"
- if (Operands.size() == 1)
- Operands.push_back(X86Operand::CreateReg(MatchRegisterName("ax"),
- 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;
+
+ // 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("sal") ||
+ 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);
}
}
- // 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);
- }
-
- // 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 &&
- static_cast<X86Operand*>(Operands[1])->isMem()) {
- delete Operands[0];
- Operands[0] = X86Operand::CreateToken("fstps", NameLoc);
- }
-
- // FIXME: Hack to handle recognize "aa[dm]" -> "aa[dm] $0xA".
- if ((Name.startswith("aad") || Name.startswith("aam")) &&
- Operands.size() == 1) {
- const MCExpr *A = MCConstantExpr::Create(0xA, getParser().getContext());
- Operands.push_back(X86Operand::CreateImm(A, NameLoc, NameLoc));
- }
-
return false;
}
// First, handle aliases that expand to multiple instructions.
// FIXME: This should be replaced with a real .td file alias mechanism.
+ // Also, MatchInstructionImpl should do actually *do* the EmitInstruction
+ // call.
if (Op->getToken() == "fstsw" || Op->getToken() == "fstcw" ||
Op->getToken() == "fstsww" || Op->getToken() == "fstcww" ||
Op->getToken() == "finit" || Op->getToken() == "fsave" ||
Tmp += ' ';
Op->setTokenValue(Tmp.str());
+ // If this instruction starts with an 'f', then it is a floating point stack
+ // instruction. These come in up to three forms for 32-bit, 64-bit, and
+ // 80-bit floating point, which use the suffixes s,l,t respectively.
+ //
+ // Otherwise, we assume that this may be an integer instruction, which comes
+ // in 8/16/32/64-bit forms using the b,w,l,q suffixes respectively.
+ const char *Suffixes = Base[0] != 'f' ? "bwlq" : "slt\0";
+
// Check for the various suffix matches.
- Tmp[Base.size()] = 'b';
- unsigned BErrorInfo, WErrorInfo, LErrorInfo, QErrorInfo;
- MatchResultTy MatchB = MatchInstructionImpl(Operands, Inst, BErrorInfo);
- Tmp[Base.size()] = 'w';
- MatchResultTy MatchW = MatchInstructionImpl(Operands, Inst, WErrorInfo);
- Tmp[Base.size()] = 'l';
- MatchResultTy MatchL = MatchInstructionImpl(Operands, Inst, LErrorInfo);
- Tmp[Base.size()] = 'q';
- MatchResultTy MatchQ = MatchInstructionImpl(Operands, Inst, QErrorInfo);
+ Tmp[Base.size()] = Suffixes[0];
+ unsigned ErrorInfoIgnore;
+ MatchResultTy Match1, Match2, Match3, Match4;
+
+ Match1 = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore);
+ Tmp[Base.size()] = Suffixes[1];
+ Match2 = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore);
+ Tmp[Base.size()] = Suffixes[2];
+ Match3 = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore);
+ Tmp[Base.size()] = Suffixes[3];
+ Match4 = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore);
// Restore the old token.
Op->setTokenValue(Base);
// instruction will already have been filled in correctly, since the failing
// matches won't have modified it).
unsigned NumSuccessfulMatches =
- (MatchB == Match_Success) + (MatchW == Match_Success) +
- (MatchL == Match_Success) + (MatchQ == Match_Success);
+ (Match1 == Match_Success) + (Match2 == Match_Success) +
+ (Match3 == Match_Success) + (Match4 == Match_Success);
if (NumSuccessfulMatches == 1) {
Out.EmitInstruction(Inst);
return false;
if (NumSuccessfulMatches > 1) {
char MatchChars[4];
unsigned NumMatches = 0;
- if (MatchB == Match_Success)
- MatchChars[NumMatches++] = 'b';
- if (MatchW == Match_Success)
- MatchChars[NumMatches++] = 'w';
- if (MatchL == Match_Success)
- MatchChars[NumMatches++] = 'l';
- if (MatchQ == Match_Success)
- MatchChars[NumMatches++] = 'q';
+ if (Match1 == Match_Success) MatchChars[NumMatches++] = Suffixes[0];
+ if (Match2 == Match_Success) MatchChars[NumMatches++] = Suffixes[1];
+ if (Match3 == Match_Success) MatchChars[NumMatches++] = Suffixes[2];
+ if (Match4 == Match_Success) MatchChars[NumMatches++] = Suffixes[3];
SmallString<126> Msg;
raw_svector_ostream OS(Msg);
// If all of the instructions reported an invalid mnemonic, then the original
// mnemonic was invalid.
- if ((MatchB == Match_MnemonicFail) && (MatchW == Match_MnemonicFail) &&
- (MatchL == Match_MnemonicFail) && (MatchQ == Match_MnemonicFail)) {
+ if ((Match1 == Match_MnemonicFail) && (Match2 == Match_MnemonicFail) &&
+ (Match3 == Match_MnemonicFail) && (Match4 == Match_MnemonicFail)) {
if (!WasOriginallyInvalidOperand) {
Error(IDLoc, "invalid instruction mnemonic '" + Base + "'");
return true;
// If one instruction matched with a missing feature, report this as a
// missing feature.
- if ((MatchB == Match_MissingFeature) + (MatchW == Match_MissingFeature) +
- (MatchL == Match_MissingFeature) + (MatchQ == Match_MissingFeature) == 1){
+ if ((Match1 == Match_MissingFeature) + (Match2 == Match_MissingFeature) +
+ (Match3 == Match_MissingFeature) + (Match4 == Match_MissingFeature) == 1){
Error(IDLoc, "instruction requires a CPU feature not currently enabled");
return true;
}
// If one instruction matched with an invalid operand, report this as an
// operand failure.
- if ((MatchB == Match_InvalidOperand) + (MatchW == Match_InvalidOperand) +
- (MatchL == Match_InvalidOperand) + (MatchQ == Match_InvalidOperand) == 1){
+ if ((Match1 == Match_InvalidOperand) + (Match2 == Match_InvalidOperand) +
+ (Match3 == Match_InvalidOperand) + (Match4 == Match_InvalidOperand) == 1){
Error(IDLoc, "invalid operand for instruction");
return true;
}