while (true) {
AsmToken::TokenKind TokKind = Lexer.getKind();
if (Lexer.getKind() == AsmToken::Identifier) {
- StringRef Identifier = Lexer.getTok().getString();
- if (Identifier.equals_lower("and"))
- TokKind = AsmToken::Amp;
- else if (Identifier.equals_lower("not"))
- TokKind = AsmToken::Exclaim;
- else if (Identifier.equals_lower("or"))
- TokKind = AsmToken::Pipe;
+ TokKind = StringSwitch<AsmToken::TokenKind>(Lexer.getTok().getString())
+ .CaseLower("and", AsmToken::Amp)
+ .CaseLower("not", AsmToken::Exclaim)
+ .CaseLower("or", AsmToken::Pipe)
+ .CaseLower("eq", AsmToken::EqualEqual)
+ .CaseLower("ne", AsmToken::ExclaimEqual)
+ .CaseLower("lt", AsmToken::Less)
+ .CaseLower("le", AsmToken::LessEqual)
+ .CaseLower("gt", AsmToken::Greater)
+ .CaseLower("ge", AsmToken::GreaterEqual)
+ .Default(TokKind);
}
MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
unsigned TokPrec = getBinOpPrecedence(TokKind, Kind);
namespace {
static const char OpPrecedence[] = {
- 0, // IC_OR
- 1, // IC_XOR
- 2, // IC_AND
- 3, // IC_LSHIFT
- 3, // IC_RSHIFT
- 4, // IC_PLUS
- 4, // IC_MINUS
- 5, // IC_MULTIPLY
- 5, // IC_DIVIDE
- 5, // IC_MOD
- 6, // IC_NOT
- 7, // IC_NEG
- 8, // IC_RPAREN
- 9, // IC_LPAREN
- 0, // IC_IMM
- 0 // IC_REGISTER
+ 0, // IC_OR
+ 1, // IC_XOR
+ 2, // IC_AND
+ 4, // IC_LSHIFT
+ 4, // IC_RSHIFT
+ 5, // IC_PLUS
+ 5, // IC_MINUS
+ 6, // IC_MULTIPLY
+ 6, // IC_DIVIDE
+ 6, // IC_MOD
+ 7, // IC_NOT
+ 8, // IC_NEG
+ 9, // IC_RPAREN
+ 10, // IC_LPAREN
+ 0, // IC_IMM
+ 0, // IC_REGISTER
+ 3, // IC_EQ
+ 3, // IC_NE
+ 3, // IC_LT
+ 3, // IC_LE
+ 3, // IC_GT
+ 3 // IC_GE
};
class X86AsmParser : public MCTargetAsmParser {
IC_RPAREN,
IC_LPAREN,
IC_IMM,
- IC_REGISTER
+ IC_REGISTER,
+ IC_EQ,
+ IC_NE,
+ IC_LT,
+ IC_LE,
+ IC_GT,
+ IC_GE
};
enum IntelOperatorKind {
Val = Op1.second >> Op2.second;
OperandStack.push_back(std::make_pair(IC_IMM, Val));
break;
+ case IC_EQ:
+ assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
+ "Equals operation with an immediate and a register!");
+ Val = (Op1.second == Op2.second) ? -1 : 0;
+ OperandStack.push_back(std::make_pair(IC_IMM, Val));
+ break;
+ case IC_NE:
+ assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
+ "Not-equals operation with an immediate and a register!");
+ Val = (Op1.second != Op2.second) ? -1 : 0;
+ OperandStack.push_back(std::make_pair(IC_IMM, Val));
+ break;
+ case IC_LT:
+ assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
+ "Less-than operation with an immediate and a register!");
+ Val = (Op1.second < Op2.second) ? -1 : 0;
+ OperandStack.push_back(std::make_pair(IC_IMM, Val));
+ break;
+ case IC_LE:
+ assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
+ "Less-than-or-equal operation with an immediate and a "
+ "register!");
+ Val = (Op1.second <= Op2.second) ? -1 : 0;
+ OperandStack.push_back(std::make_pair(IC_IMM, Val));
+ break;
+ case IC_GT:
+ assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
+ "Greater-than operation with an immediate and a register!");
+ Val = (Op1.second > Op2.second) ? -1 : 0;
+ OperandStack.push_back(std::make_pair(IC_IMM, Val));
+ break;
+ case IC_GE:
+ assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
+ "Greater-than-or-equal operation with an immediate and a "
+ "register!");
+ Val = (Op1.second >= Op2.second) ? -1 : 0;
+ OperandStack.push_back(std::make_pair(IC_IMM, Val));
+ break;
}
}
}
IES_OR,
IES_XOR,
IES_AND,
+ IES_EQ,
+ IES_NE,
+ IES_LT,
+ IES_LE,
+ IES_GT,
+ IES_GE,
IES_LSHIFT,
IES_RSHIFT,
IES_PLUS,
}
PrevState = CurrState;
}
+ void onEq() {
+ IntelExprState CurrState = State;
+ switch (State) {
+ default:
+ State = IES_ERROR;
+ break;
+ case IES_INTEGER:
+ case IES_RPAREN:
+ case IES_REGISTER:
+ State = IES_EQ;
+ IC.pushOperator(IC_EQ);
+ break;
+ }
+ PrevState = CurrState;
+ }
+ void onNE() {
+ IntelExprState CurrState = State;
+ switch (State) {
+ default:
+ State = IES_ERROR;
+ break;
+ case IES_INTEGER:
+ case IES_RPAREN:
+ case IES_REGISTER:
+ State = IES_NE;
+ IC.pushOperator(IC_NE);
+ break;
+ }
+ PrevState = CurrState;
+ }
+ void onLT() {
+ IntelExprState CurrState = State;
+ switch (State) {
+ default:
+ State = IES_ERROR;
+ break;
+ case IES_INTEGER:
+ case IES_RPAREN:
+ case IES_REGISTER:
+ State = IES_LT;
+ IC.pushOperator(IC_LT);
+ break;
+ }
+ PrevState = CurrState;
+ }
+ void onLE() {
+ IntelExprState CurrState = State;
+ switch (State) {
+ default:
+ State = IES_ERROR;
+ break;
+ case IES_INTEGER:
+ case IES_RPAREN:
+ case IES_REGISTER:
+ State = IES_LE;
+ IC.pushOperator(IC_LE);
+ break;
+ }
+ PrevState = CurrState;
+ }
+ void onGT() {
+ IntelExprState CurrState = State;
+ switch (State) {
+ default:
+ State = IES_ERROR;
+ break;
+ case IES_INTEGER:
+ case IES_RPAREN:
+ case IES_REGISTER:
+ State = IES_GT;
+ IC.pushOperator(IC_GT);
+ break;
+ }
+ PrevState = CurrState;
+ }
+ void onGE() {
+ IntelExprState CurrState = State;
+ switch (State) {
+ default:
+ State = IES_ERROR;
+ break;
+ case IES_INTEGER:
+ case IES_RPAREN:
+ case IES_REGISTER:
+ State = IES_GE;
+ IC.pushOperator(IC_GE);
+ break;
+ }
+ PrevState = CurrState;
+ }
void onLShift() {
IntelExprState CurrState = State;
switch (State) {
case IES_OR:
case IES_XOR:
case IES_AND:
+ case IES_EQ:
+ case IES_NE:
+ case IES_LT:
+ case IES_LE:
+ case IES_GT:
+ case IES_GE:
case IES_LSHIFT:
case IES_RSHIFT:
case IES_PLUS:
case IES_OR:
case IES_XOR:
case IES_AND:
+ case IES_EQ:
+ case IES_NE:
+ case IES_LT:
+ case IES_LE:
+ case IES_GT:
+ case IES_GE:
case IES_LSHIFT:
case IES_RSHIFT:
case IES_PLUS:
case IES_OR:
case IES_XOR:
case IES_AND:
+ case IES_EQ:
+ case IES_NE:
+ case IES_LT:
+ case IES_LE:
+ case IES_GT:
+ case IES_GE:
case IES_LSHIFT:
case IES_RSHIFT:
case IES_DIVIDE:
case IES_OR:
case IES_XOR:
case IES_AND:
+ case IES_EQ:
+ case IES_NE:
+ case IES_LT:
+ case IES_LE:
+ case IES_GT:
+ case IES_GE:
case IES_LSHIFT:
case IES_RSHIFT:
case IES_MULTIPLY:
bool ParseRoundingModeOp(SMLoc Start, OperandVector &Operands);
bool ParseIntelNamedOperator(StringRef Name, IntelExprStateMachine &SM,
bool &ParseError, SMLoc &End);
+ bool ParseMasmNamedOperator(StringRef Name, IntelExprStateMachine &SM,
+ bool &ParseError, SMLoc &End);
void RewriteIntelExpression(IntelExprStateMachine &SM, SMLoc Start,
SMLoc End);
bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End);
bool X86AsmParser::ParseIntelNamedOperator(StringRef Name,
IntelExprStateMachine &SM,
bool &ParseError, SMLoc &End) {
- // A named operator should be either lower or upper case, but not a mix
- if (Name.compare(Name.lower()) && Name.compare(Name.upper()))
+ // A named operator should be either lower or upper case, but not a mix...
+ // except in MASM, which uses full case-insensitivity.
+ if (Name.compare(Name.lower()) && Name.compare(Name.upper()) &&
+ !getParser().isParsingMasm())
return false;
if (Name.equals_lower("not")) {
SM.onNot();
End = consumeToken();
return true;
}
+bool X86AsmParser::ParseMasmNamedOperator(StringRef Name,
+ IntelExprStateMachine &SM,
+ bool &ParseError, SMLoc &End) {
+ if (Name.equals_lower("eq")) {
+ SM.onEq();
+ } else if (Name.equals_lower("ne")) {
+ SM.onNE();
+ } else if (Name.equals_lower("lt")) {
+ SM.onLT();
+ } else if (Name.equals_lower("le")) {
+ SM.onLE();
+ } else if (Name.equals_lower("gt")) {
+ SM.onGT();
+ } else if (Name.equals_lower("ge")) {
+ SM.onGE();
+ } else {
+ return false;
+ }
+ End = consumeToken();
+ return true;
+}
bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
MCAsmParser &Parser = getParser();
return true;
break;
}
+ if (Parser.isParsingMasm() &&
+ ParseMasmNamedOperator(Identifier, SM, ParseError, End)) {
+ if (ParseError)
+ return true;
+ break;
+ }
// Symbol reference, when parsing assembly content
InlineAsmIdentifierInfo Info;
AsmFieldInfo FieldInfo;
--- /dev/null
+; RUN: llvm-ml -filetype=asm %s | FileCheck %s
+
+.data
+
+t1 BYTE NOT 1
+; CHECK-LABEL: t1:
+; CHECK-NEXT: .byte -2
+; CHECK-NOT: .byte
+
+t2 BYTE 1 OR 2
+; CHECK-LABEL: t2:
+; CHECK-NEXT: .byte 3
+
+t3 BYTE 6 AND 10
+; CHECK-LABEL: t3:
+; CHECK-NEXT: .byte 2
+
+t4 BYTE 5 EQ 6
+ BYTE 6 EQ 6
+ BYTE 7 EQ 6
+; CHECK-LABEL: t4:
+; CHECK-NEXT: .byte 0
+; CHECK: .byte -1
+; CHECK: .byte 0
+; CHECK-NOT: .byte
+
+t5 BYTE 5 NE 6
+ BYTE 6 NE 6
+ BYTE 7 NE 6
+; CHECK-LABEL: t5:
+; CHECK-NEXT: .byte -1
+; CHECK: .byte 0
+; CHECK: .byte -1
+; CHECK-NOT: .byte
+
+t6 BYTE 5 LT 6
+ BYTE 6 LT 6
+ BYTE 7 LT 6
+; CHECK-LABEL: t6:
+; CHECK-NEXT: .byte -1
+; CHECK: .byte 0
+; CHECK: .byte 0
+; CHECK-NOT: .byte
+
+t7 BYTE 5 LE 6
+ BYTE 6 LE 6
+ BYTE 7 LE 6
+; CHECK-LABEL: t7:
+; CHECK-NEXT: .byte -1
+; CHECK: .byte -1
+; CHECK: .byte 0
+; CHECK-NOT: .byte
+
+t8 BYTE 5 GT 6
+ BYTE 6 GT 6
+ BYTE 7 GT 6
+; CHECK-LABEL: t8:
+; CHECK-NEXT: .byte 0
+; CHECK: .byte 0
+; CHECK: .byte -1
+; CHECK-NOT: .byte
+
+t9 BYTE 5 GE 6
+ BYTE 6 GE 6
+ BYTE 7 GE 6
+; CHECK-LABEL: t9:
+; CHECK-NEXT: .byte 0
+; CHECK: .byte -1
+; CHECK: .byte -1
+; CHECK-NOT: .byte
+
+.code
+
+t10:
+xor eax, Not 1
+; CHECK-LABEL: t10:
+; CHECK-NEXT: xor eax, -2
+
+t11:
+xor eax, 1 oR 2
+; CHECK-LABEL: t11:
+; CHECK-NEXT: xor eax, 3
+
+t12:
+xor eax, 6 ANd 10
+; CHECK-LABEL: t12:
+; CHECK-NEXT: xor eax, 2
+
+t13:
+xor eax, 5 Eq 6
+xor eax, 6 eQ 6
+xor eax, 7 eq 6
+; CHECK-LABEL: t13:
+; CHECK-NEXT: xor eax, 0
+; CHECK-NEXT: xor eax, -1
+; CHECK-NEXT: xor eax, 0
+
+t14:
+xor eax, 5 Ne 6
+xor eax, 6 nE 6
+xor eax, 7 ne 6
+; CHECK-LABEL: t14:
+; CHECK-NEXT: xor eax, -1
+; CHECK-NEXT: xor eax, 0
+; CHECK-NEXT: xor eax, -1
+
+t15:
+xor eax, 5 Lt 6
+xor eax, 6 lT 6
+xor eax, 7 lt 6
+; CHECK-LABEL: t15:
+; CHECK-NEXT: xor eax, -1
+; CHECK-NEXT: xor eax, 0
+; CHECK-NEXT: xor eax, 0
+
+t16:
+xor eax, 5 Le 6
+xor eax, 6 lE 6
+xor eax, 7 le 6
+; CHECK-LABEL: t16:
+; CHECK-NEXT: xor eax, -1
+; CHECK-NEXT: xor eax, -1
+; CHECK-NEXT: xor eax, 0
+
+t17:
+xor eax, 5 Gt 6
+xor eax, 6 gT 6
+xor eax, 7 gt 6
+; CHECK-LABEL: t17:
+; CHECK-NEXT: xor eax, 0
+; CHECK-NEXT: xor eax, 0
+; CHECK-NEXT: xor eax, -1
+
+t18:
+xor eax, 5 Ge 6
+xor eax, 6 gE 6
+xor eax, 7 ge 6
+; CHECK-LABEL: t18:
+; CHECK-NEXT: xor eax, 0
+; CHECK-NEXT: xor eax, -1
+; CHECK-NEXT: xor eax, -1
+
+END