blob: da376657c34d3d54dd0cfd493881c98c88a6dff3 [file] [log] [blame]
Daniel Dunbar71475772009-07-17 20:42:00 +00001//===-- X86AsmParser.cpp - Parse X86 assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattnerf29c0b62010-01-14 22:21:20 +000010#include "llvm/Target/TargetAsmParser.h"
Daniel Dunbar67038c12009-07-18 23:03:22 +000011#include "X86.h"
Daniel Dunbareefe8612010-07-19 05:44:09 +000012#include "X86Subtarget.h"
Chris Lattner1261b812010-09-22 04:11:10 +000013#include "llvm/Target/TargetRegistry.h"
14#include "llvm/Target/TargetAsmParser.h"
Kevin Enderbyce4bec82009-09-10 20:51:44 +000015#include "llvm/MC/MCStreamer.h"
Daniel Dunbar73da11e2009-08-31 08:08:38 +000016#include "llvm/MC/MCExpr.h"
Daniel Dunbarb6d6aa22009-07-31 02:32:59 +000017#include "llvm/MC/MCInst.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000018#include "llvm/MC/MCParser/MCAsmLexer.h"
19#include "llvm/MC/MCParser/MCAsmParser.h"
20#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Chris Lattner1261b812010-09-22 04:11:10 +000021#include "llvm/ADT/SmallString.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/ADT/StringExtras.h"
24#include "llvm/ADT/StringSwitch.h"
25#include "llvm/ADT/Twine.h"
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000026#include "llvm/Support/SourceMgr.h"
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +000027#include "llvm/Support/raw_ostream.h"
Daniel Dunbar71475772009-07-17 20:42:00 +000028using namespace llvm;
29
30namespace {
Benjamin Kramerb60210e2009-07-31 11:35:26 +000031struct X86Operand;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000032
33class X86ATTAsmParser : public TargetAsmParser {
34 MCAsmParser &Parser;
Daniel Dunbar419197c2010-07-19 00:33:49 +000035 TargetMachine &TM;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000036
Daniel Dunbar63ec0932010-03-18 20:06:02 +000037protected:
38 unsigned Is64Bit : 1;
39
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000040private:
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000041 MCAsmParser &getParser() const { return Parser; }
42
43 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
44
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000045 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
46
Chris Lattner0c2538f2010-01-15 18:51:29 +000047 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000048
Chris Lattnera2bbb7c2010-01-15 18:44:13 +000049 X86Operand *ParseOperand();
Chris Lattnerb9270732010-04-17 18:56:34 +000050 X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
Kevin Enderbyce4bec82009-09-10 20:51:44 +000051
52 bool ParseDirectiveWord(unsigned Size, SMLoc L);
53
Daniel Dunbar2ecc3bb2010-08-12 00:55:38 +000054 bool MatchInstruction(SMLoc IDLoc,
55 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbare10787e2009-08-07 08:26:05 +000056 MCInst &Inst);
57
Daniel Dunbareefe8612010-07-19 05:44:09 +000058 /// @name Auto-generated Matcher Functions
59 /// {
Chris Lattner3e4582a2010-09-06 19:11:01 +000060
61#define GET_ASSEMBLER_HEADER
62#include "X86GenAsmMatcher.inc"
63
Daniel Dunbar00331992009-07-29 00:02:19 +000064 /// }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000065
66public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000067 X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
Daniel Dunbareefe8612010-07-19 05:44:09 +000068 : TargetAsmParser(T), Parser(_Parser), TM(TM) {
69
70 // Initialize the set of available features.
71 setAvailableFeatures(ComputeAvailableFeatures(
72 &TM.getSubtarget<X86Subtarget>()));
73 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000074
Benjamin Kramer92d89982010-07-14 22:38:02 +000075 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattnerf29c0b62010-01-14 22:21:20 +000076 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderbyce4bec82009-09-10 20:51:44 +000077
78 virtual bool ParseDirective(AsmToken DirectiveID);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000079};
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +000080
Daniel Dunbar63ec0932010-03-18 20:06:02 +000081class X86_32ATTAsmParser : public X86ATTAsmParser {
82public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000083 X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
84 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbar63ec0932010-03-18 20:06:02 +000085 Is64Bit = false;
86 }
87};
88
89class X86_64ATTAsmParser : public X86ATTAsmParser {
90public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000091 X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
92 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbar63ec0932010-03-18 20:06:02 +000093 Is64Bit = true;
94 }
95};
96
Chris Lattner4eb9df02009-07-29 06:33:53 +000097} // end anonymous namespace
98
Sean Callanan86c11812010-01-23 00:40:33 +000099/// @name Auto-generated Match Functions
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000100/// {
Sean Callanan86c11812010-01-23 00:40:33 +0000101
Chris Lattner60db0a62010-02-09 00:34:28 +0000102static unsigned MatchRegisterName(StringRef Name);
Sean Callanan86c11812010-01-23 00:40:33 +0000103
104/// }
Chris Lattner4eb9df02009-07-29 06:33:53 +0000105
106namespace {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000107
108/// X86Operand - Instances of this class represent a parsed X86 machine
109/// instruction.
Chris Lattner872501b2010-01-14 21:20:55 +0000110struct X86Operand : public MCParsedAsmOperand {
Chris Lattner86e61532010-01-15 19:06:59 +0000111 enum KindTy {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000112 Token,
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000113 Register,
114 Immediate,
115 Memory
116 } Kind;
117
Chris Lattner0c2538f2010-01-15 18:51:29 +0000118 SMLoc StartLoc, EndLoc;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000119
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000120 union {
121 struct {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000122 const char *Data;
123 unsigned Length;
124 } Tok;
125
126 struct {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000127 unsigned RegNo;
128 } Reg;
129
130 struct {
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000131 const MCExpr *Val;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000132 } Imm;
133
134 struct {
135 unsigned SegReg;
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000136 const MCExpr *Disp;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000137 unsigned BaseReg;
138 unsigned IndexReg;
139 unsigned Scale;
140 } Mem;
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +0000141 };
Daniel Dunbar71475772009-07-17 20:42:00 +0000142
Chris Lattner015cfb12010-01-15 19:33:43 +0000143 X86Operand(KindTy K, SMLoc Start, SMLoc End)
Chris Lattner86e61532010-01-15 19:06:59 +0000144 : Kind(K), StartLoc(Start), EndLoc(End) {}
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000145
Chris Lattner86e61532010-01-15 19:06:59 +0000146 /// getStartLoc - Get the location of the first token of this operand.
147 SMLoc getStartLoc() const { return StartLoc; }
148 /// getEndLoc - Get the location of the last token of this operand.
149 SMLoc getEndLoc() const { return EndLoc; }
150
Daniel Dunbarebace222010-08-11 06:37:04 +0000151 virtual void dump(raw_ostream &OS) const {}
152
Daniel Dunbare10787e2009-08-07 08:26:05 +0000153 StringRef getToken() const {
154 assert(Kind == Token && "Invalid access!");
155 return StringRef(Tok.Data, Tok.Length);
156 }
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000157 void setTokenValue(StringRef Value) {
158 assert(Kind == Token && "Invalid access!");
159 Tok.Data = Value.data();
160 Tok.Length = Value.size();
161 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000162
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000163 unsigned getReg() const {
164 assert(Kind == Register && "Invalid access!");
165 return Reg.RegNo;
166 }
Daniel Dunbarf59ee962009-07-28 20:47:52 +0000167
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000168 const MCExpr *getImm() const {
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000169 assert(Kind == Immediate && "Invalid access!");
170 return Imm.Val;
171 }
172
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000173 const MCExpr *getMemDisp() const {
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000174 assert(Kind == Memory && "Invalid access!");
175 return Mem.Disp;
176 }
177 unsigned getMemSegReg() const {
178 assert(Kind == Memory && "Invalid access!");
179 return Mem.SegReg;
180 }
181 unsigned getMemBaseReg() const {
182 assert(Kind == Memory && "Invalid access!");
183 return Mem.BaseReg;
184 }
185 unsigned getMemIndexReg() const {
186 assert(Kind == Memory && "Invalid access!");
187 return Mem.IndexReg;
188 }
189 unsigned getMemScale() const {
190 assert(Kind == Memory && "Invalid access!");
191 return Mem.Scale;
192 }
193
Daniel Dunbar541efcc2009-08-08 07:50:56 +0000194 bool isToken() const {return Kind == Token; }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000195
196 bool isImm() const { return Kind == Immediate; }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000197
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000198 bool isImmSExti16i8() const {
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000199 if (!isImm())
200 return false;
201
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000202 // If this isn't a constant expr, just assume it fits and let relaxation
203 // handle it.
204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
205 if (!CE)
206 return true;
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000207
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000208 // Otherwise, check the value is in a range that makes sense for this
209 // extension.
210 uint64_t Value = CE->getValue();
211 return (( Value <= 0x000000000000007FULL)||
212 (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)||
213 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000214 }
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000215 bool isImmSExti32i8() const {
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000216 if (!isImm())
217 return false;
218
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000219 // If this isn't a constant expr, just assume it fits and let relaxation
220 // handle it.
221 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
222 if (!CE)
223 return true;
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000224
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000225 // Otherwise, check the value is in a range that makes sense for this
226 // extension.
227 uint64_t Value = CE->getValue();
228 return (( Value <= 0x000000000000007FULL)||
229 (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
230 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
231 }
232 bool isImmSExti64i8() const {
233 if (!isImm())
234 return false;
235
236 // If this isn't a constant expr, just assume it fits and let relaxation
237 // handle it.
238 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
239 if (!CE)
240 return true;
241
242 // Otherwise, check the value is in a range that makes sense for this
243 // extension.
244 uint64_t Value = CE->getValue();
245 return (( Value <= 0x000000000000007FULL)||
246 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
247 }
248 bool isImmSExti64i32() const {
249 if (!isImm())
250 return false;
251
252 // If this isn't a constant expr, just assume it fits and let relaxation
253 // handle it.
254 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
255 if (!CE)
256 return true;
257
258 // Otherwise, check the value is in a range that makes sense for this
259 // extension.
260 uint64_t Value = CE->getValue();
261 return (( Value <= 0x000000007FFFFFFFULL)||
262 (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000263 }
264
Daniel Dunbare10787e2009-08-07 08:26:05 +0000265 bool isMem() const { return Kind == Memory; }
266
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000267 bool isAbsMem() const {
268 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
Daniel Dunbar3184f222010-02-02 21:44:16 +0000269 !getMemIndexReg() && getMemScale() == 1;
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000270 }
271
Daniel Dunbare10787e2009-08-07 08:26:05 +0000272 bool isReg() const { return Kind == Register; }
273
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000274 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
275 // Add as immediates when possible.
276 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
277 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
278 else
279 Inst.addOperand(MCOperand::CreateExpr(Expr));
280 }
281
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000282 void addRegOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000283 assert(N == 1 && "Invalid number of operands!");
284 Inst.addOperand(MCOperand::CreateReg(getReg()));
285 }
286
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000287 void addImmOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000288 assert(N == 1 && "Invalid number of operands!");
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000289 addExpr(Inst, getImm());
Daniel Dunbare10787e2009-08-07 08:26:05 +0000290 }
291
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000292 void addMemOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbara97adee2010-01-30 00:24:00 +0000293 assert((N == 5) && "Invalid number of operands!");
Daniel Dunbare10787e2009-08-07 08:26:05 +0000294 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
295 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
296 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000297 addExpr(Inst, getMemDisp());
Daniel Dunbara97adee2010-01-30 00:24:00 +0000298 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
299 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000300
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000301 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
302 assert((N == 1) && "Invalid number of operands!");
303 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
304 }
305
Chris Lattner528d00b2010-01-15 19:28:38 +0000306 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
307 X86Operand *Res = new X86Operand(Token, Loc, Loc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000308 Res->Tok.Data = Str.data();
309 Res->Tok.Length = Str.size();
Daniel Dunbare10787e2009-08-07 08:26:05 +0000310 return Res;
311 }
312
Chris Lattner0c2538f2010-01-15 18:51:29 +0000313 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
Chris Lattner86e61532010-01-15 19:06:59 +0000314 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000315 Res->Reg.RegNo = RegNo;
Chris Lattner0c2538f2010-01-15 18:51:29 +0000316 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000317 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000318
Chris Lattner528d00b2010-01-15 19:28:38 +0000319 static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
320 X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000321 Res->Imm.Val = Val;
322 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000323 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000324
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000325 /// Create an absolute memory operand.
326 static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
327 SMLoc EndLoc) {
328 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
329 Res->Mem.SegReg = 0;
330 Res->Mem.Disp = Disp;
331 Res->Mem.BaseReg = 0;
332 Res->Mem.IndexReg = 0;
Daniel Dunbar3184f222010-02-02 21:44:16 +0000333 Res->Mem.Scale = 1;
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000334 return Res;
335 }
336
337 /// Create a generalized memory operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000338 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
339 unsigned BaseReg, unsigned IndexReg,
Chris Lattner015cfb12010-01-15 19:33:43 +0000340 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000341 // We should never just have a displacement, that should be parsed as an
342 // absolute memory operand.
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000343 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
344
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000345 // The scale should always be one of {1,2,4,8}.
346 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000347 "Invalid scale!");
Chris Lattner015cfb12010-01-15 19:33:43 +0000348 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000349 Res->Mem.SegReg = SegReg;
350 Res->Mem.Disp = Disp;
351 Res->Mem.BaseReg = BaseReg;
352 Res->Mem.IndexReg = IndexReg;
353 Res->Mem.Scale = Scale;
354 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000355 }
356};
Daniel Dunbar3c2a8932009-07-20 18:55:04 +0000357
Chris Lattner4eb9df02009-07-29 06:33:53 +0000358} // end anonymous namespace.
Daniel Dunbarf59ee962009-07-28 20:47:52 +0000359
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000360
Chris Lattner0c2538f2010-01-15 18:51:29 +0000361bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
362 SMLoc &StartLoc, SMLoc &EndLoc) {
Chris Lattnercc2ad082010-01-15 18:27:19 +0000363 RegNo = 0;
Sean Callanan936b0d32010-01-19 21:44:56 +0000364 const AsmToken &TokPercent = Parser.getTok();
Kevin Enderby7d912182009-09-03 17:15:07 +0000365 assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
Chris Lattner0c2538f2010-01-15 18:51:29 +0000366 StartLoc = TokPercent.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000367 Parser.Lex(); // Eat percent token.
Kevin Enderby7d912182009-09-03 17:15:07 +0000368
Sean Callanan936b0d32010-01-19 21:44:56 +0000369 const AsmToken &Tok = Parser.getTok();
Kevin Enderbyc0edda32009-09-16 17:18:29 +0000370 if (Tok.isNot(AsmToken::Identifier))
371 return Error(Tok.getLoc(), "invalid register name");
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000372
Daniel Dunbar00331992009-07-29 00:02:19 +0000373 // FIXME: Validate register for the current architecture; we have to do
374 // validation later, so maybe there is no need for this here.
Kevin Enderby7d912182009-09-03 17:15:07 +0000375 RegNo = MatchRegisterName(Tok.getString());
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000376
Chris Lattner1261b812010-09-22 04:11:10 +0000377 // If the match failed, try the register name as lowercase.
378 if (RegNo == 0)
379 RegNo = MatchRegisterName(LowercaseString(Tok.getString()));
380
Bruno Cardoso Lopes306a1f92010-07-24 00:06:39 +0000381 // FIXME: This should be done using Requires<In32BitMode> and
382 // Requires<In64BitMode> so "eiz" usage in 64-bit instructions
383 // can be also checked.
384 if (RegNo == X86::RIZ && !Is64Bit)
385 return Error(Tok.getLoc(), "riz register in 64-bit mode only");
386
Chris Lattner1261b812010-09-22 04:11:10 +0000387 // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens.
388 if (RegNo == 0 && (Tok.getString() == "st" || Tok.getString() == "ST")) {
Chris Lattnerd00faaa2010-02-09 00:49:22 +0000389 RegNo = X86::ST0;
390 EndLoc = Tok.getLoc();
391 Parser.Lex(); // Eat 'st'
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000392
Chris Lattnerd00faaa2010-02-09 00:49:22 +0000393 // Check to see if we have '(4)' after %st.
394 if (getLexer().isNot(AsmToken::LParen))
395 return false;
396 // Lex the paren.
397 getParser().Lex();
398
399 const AsmToken &IntTok = Parser.getTok();
400 if (IntTok.isNot(AsmToken::Integer))
401 return Error(IntTok.getLoc(), "expected stack index");
402 switch (IntTok.getIntVal()) {
403 case 0: RegNo = X86::ST0; break;
404 case 1: RegNo = X86::ST1; break;
405 case 2: RegNo = X86::ST2; break;
406 case 3: RegNo = X86::ST3; break;
407 case 4: RegNo = X86::ST4; break;
408 case 5: RegNo = X86::ST5; break;
409 case 6: RegNo = X86::ST6; break;
410 case 7: RegNo = X86::ST7; break;
411 default: return Error(IntTok.getLoc(), "invalid stack index");
412 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000413
Chris Lattnerd00faaa2010-02-09 00:49:22 +0000414 if (getParser().Lex().isNot(AsmToken::RParen))
415 return Error(Parser.getTok().getLoc(), "expected ')'");
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000416
Chris Lattnerd00faaa2010-02-09 00:49:22 +0000417 EndLoc = Tok.getLoc();
418 Parser.Lex(); // Eat ')'
419 return false;
420 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000421
Chris Lattner80486622010-06-24 07:29:18 +0000422 // If this is "db[0-7]", match it as an alias
423 // for dr[0-7].
424 if (RegNo == 0 && Tok.getString().size() == 3 &&
425 Tok.getString().startswith("db")) {
426 switch (Tok.getString()[2]) {
427 case '0': RegNo = X86::DR0; break;
428 case '1': RegNo = X86::DR1; break;
429 case '2': RegNo = X86::DR2; break;
430 case '3': RegNo = X86::DR3; break;
431 case '4': RegNo = X86::DR4; break;
432 case '5': RegNo = X86::DR5; break;
433 case '6': RegNo = X86::DR6; break;
434 case '7': RegNo = X86::DR7; break;
435 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000436
Chris Lattner80486622010-06-24 07:29:18 +0000437 if (RegNo != 0) {
438 EndLoc = Tok.getLoc();
439 Parser.Lex(); // Eat it.
440 return false;
441 }
442 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000443
Daniel Dunbar66f4f542009-08-08 21:22:41 +0000444 if (RegNo == 0)
Daniel Dunbar00331992009-07-29 00:02:19 +0000445 return Error(Tok.getLoc(), "invalid register name");
446
Chris Lattner0c2538f2010-01-15 18:51:29 +0000447 EndLoc = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000448 Parser.Lex(); // Eat identifier token.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000449 return false;
Daniel Dunbar71475772009-07-17 20:42:00 +0000450}
451
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000452X86Operand *X86ATTAsmParser::ParseOperand() {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000453 switch (getLexer().getKind()) {
454 default:
Chris Lattnerb9270732010-04-17 18:56:34 +0000455 // Parse a memory operand with no segment register.
456 return ParseMemOperand(0, Parser.getTok().getLoc());
Chris Lattnercc2ad082010-01-15 18:27:19 +0000457 case AsmToken::Percent: {
Chris Lattnerb9270732010-04-17 18:56:34 +0000458 // Read the register.
Chris Lattnercc2ad082010-01-15 18:27:19 +0000459 unsigned RegNo;
Chris Lattner0c2538f2010-01-15 18:51:29 +0000460 SMLoc Start, End;
461 if (ParseRegister(RegNo, Start, End)) return 0;
Bruno Cardoso Lopes306a1f92010-07-24 00:06:39 +0000462 if (RegNo == X86::EIZ || RegNo == X86::RIZ) {
463 Error(Start, "eiz and riz can only be used as index registers");
464 return 0;
465 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000466
Chris Lattnerb9270732010-04-17 18:56:34 +0000467 // If this is a segment register followed by a ':', then this is the start
468 // of a memory reference, otherwise this is a normal register reference.
469 if (getLexer().isNot(AsmToken::Colon))
470 return X86Operand::CreateReg(RegNo, Start, End);
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000471
472
Chris Lattnerb9270732010-04-17 18:56:34 +0000473 getParser().Lex(); // Eat the colon.
474 return ParseMemOperand(RegNo, Start);
Chris Lattnercc2ad082010-01-15 18:27:19 +0000475 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000476 case AsmToken::Dollar: {
477 // $42 -> immediate.
Sean Callanan936b0d32010-01-19 21:44:56 +0000478 SMLoc Start = Parser.getTok().getLoc(), End;
Sean Callanana83fd7d2010-01-19 20:27:46 +0000479 Parser.Lex();
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000480 const MCExpr *Val;
Chris Lattnere17df0b2010-01-15 19:39:23 +0000481 if (getParser().ParseExpression(Val, End))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000482 return 0;
Chris Lattner528d00b2010-01-15 19:28:38 +0000483 return X86Operand::CreateImm(Val, Start, End);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000484 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000485 }
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +0000486}
487
Chris Lattnerb9270732010-04-17 18:56:34 +0000488/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
489/// has already been parsed if present.
490X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000491
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000492 // We have to disambiguate a parenthesized expression "(4+5)" from the start
493 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
Chris Lattner807a3bc2010-01-24 01:07:33 +0000494 // only way to do this without lookahead is to eat the '(' and see what is
495 // after it.
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000496 const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000497 if (getLexer().isNot(AsmToken::LParen)) {
Chris Lattnere17df0b2010-01-15 19:39:23 +0000498 SMLoc ExprEnd;
499 if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000500
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000501 // After parsing the base expression we could either have a parenthesized
502 // memory address or not. If not, return now. If so, eat the (.
503 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000504 // Unless we have a segment register, treat this as an immediate.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000505 if (SegReg == 0)
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000506 return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
Chris Lattner015cfb12010-01-15 19:33:43 +0000507 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000508 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000509
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000510 // Eat the '('.
Sean Callanana83fd7d2010-01-19 20:27:46 +0000511 Parser.Lex();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000512 } else {
513 // Okay, we have a '('. We don't know if this is an expression or not, but
514 // so we have to eat the ( to see beyond it.
Sean Callanan936b0d32010-01-19 21:44:56 +0000515 SMLoc LParenLoc = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000516 Parser.Lex(); // Eat the '('.
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000517
Kevin Enderby7d912182009-09-03 17:15:07 +0000518 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000519 // Nothing to do here, fall into the code below with the '(' part of the
520 // memory operand consumed.
521 } else {
Chris Lattner528d00b2010-01-15 19:28:38 +0000522 SMLoc ExprEnd;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000523
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000524 // It must be an parenthesized expression, parse it now.
Chris Lattner528d00b2010-01-15 19:28:38 +0000525 if (getParser().ParseParenExpression(Disp, ExprEnd))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000526 return 0;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000527
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000528 // After parsing the base expression we could either have a parenthesized
529 // memory address or not. If not, return now. If so, eat the (.
530 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000531 // Unless we have a segment register, treat this as an immediate.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000532 if (SegReg == 0)
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000533 return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
Chris Lattner015cfb12010-01-15 19:33:43 +0000534 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000535 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000536
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000537 // Eat the '('.
Sean Callanana83fd7d2010-01-19 20:27:46 +0000538 Parser.Lex();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000539 }
540 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000541
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000542 // If we reached here, then we just ate the ( of the memory operand. Process
543 // the rest of the memory operand.
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000544 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000545
Chris Lattner0c2538f2010-01-15 18:51:29 +0000546 if (getLexer().is(AsmToken::Percent)) {
547 SMLoc L;
548 if (ParseRegister(BaseReg, L, L)) return 0;
Bruno Cardoso Lopes306a1f92010-07-24 00:06:39 +0000549 if (BaseReg == X86::EIZ || BaseReg == X86::RIZ) {
550 Error(L, "eiz and riz can only be used as index registers");
551 return 0;
552 }
Chris Lattner0c2538f2010-01-15 18:51:29 +0000553 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000554
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000555 if (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +0000556 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000557
558 // Following the comma we should have either an index register, or a scale
559 // value. We don't support the later form, but we want to parse it
560 // correctly.
561 //
562 // Not that even though it would be completely consistent to support syntax
Bruno Cardoso Lopes306a1f92010-07-24 00:06:39 +0000563 // like "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
Kevin Enderby7d912182009-09-03 17:15:07 +0000564 if (getLexer().is(AsmToken::Percent)) {
Chris Lattner0c2538f2010-01-15 18:51:29 +0000565 SMLoc L;
566 if (ParseRegister(IndexReg, L, L)) return 0;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000567
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000568 if (getLexer().isNot(AsmToken::RParen)) {
569 // Parse the scale amount:
570 // ::= ',' [scale-expression]
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000571 if (getLexer().isNot(AsmToken::Comma)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000572 Error(Parser.getTok().getLoc(),
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000573 "expected comma in scale expression");
574 return 0;
575 }
Sean Callanana83fd7d2010-01-19 20:27:46 +0000576 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000577
578 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000579 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000580
581 int64_t ScaleVal;
582 if (getParser().ParseAbsoluteExpression(ScaleVal))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000583 return 0;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000584
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000585 // Validate the scale amount.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000586 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
587 Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
588 return 0;
589 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000590 Scale = (unsigned)ScaleVal;
591 }
592 }
593 } else if (getLexer().isNot(AsmToken::RParen)) {
Daniel Dunbar94b84a12010-08-24 19:13:38 +0000594 // A scale amount without an index is ignored.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000595 // index.
Sean Callanan936b0d32010-01-19 21:44:56 +0000596 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000597
598 int64_t Value;
599 if (getParser().ParseAbsoluteExpression(Value))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000600 return 0;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000601
Daniel Dunbar94b84a12010-08-24 19:13:38 +0000602 if (Value != 1)
603 Warning(Loc, "scale factor without index register is ignored");
604 Scale = 1;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000605 }
606 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000607
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000608 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000609 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000610 Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000611 return 0;
612 }
Sean Callanan936b0d32010-01-19 21:44:56 +0000613 SMLoc MemEnd = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000614 Parser.Lex(); // Eat the ')'.
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000615
Chris Lattner015cfb12010-01-15 19:33:43 +0000616 return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
617 MemStart, MemEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000618}
619
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000620bool X86ATTAsmParser::
Benjamin Kramer92d89982010-07-14 22:38:02 +0000621ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000622 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000623 // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
624 // represent alternative syntaxes in the .td file, without requiring
625 // instruction duplication.
626 StringRef PatchedName = StringSwitch<StringRef>(Name)
627 .Case("sal", "shl")
628 .Case("salb", "shlb")
629 .Case("sall", "shll")
630 .Case("salq", "shlq")
631 .Case("salw", "shlw")
632 .Case("repe", "rep")
633 .Case("repz", "rep")
634 .Case("repnz", "repne")
Chris Lattner063363f2010-09-08 05:38:31 +0000635 .Case("iret", "iretl")
Chris Lattnera9ca7832010-09-08 05:45:34 +0000636 .Case("sysret", "sysretl")
Chris Lattner882626c2010-09-27 07:21:41 +0000637 .Case("cwde", "cwtl")
638 .Case("cdqe", "cltq")
Chris Lattner972c60d2010-09-27 07:11:53 +0000639 .Case("smovb", "movsb")
640 .Case("smovw", "movsw")
641 .Case("smovl", "movsl")
642 .Case("smovq", "movsq")
Chris Lattner415e04f2010-09-06 23:40:56 +0000643 .Case("push", Is64Bit ? "pushq" : "pushl")
Chris Lattner8ead2372010-09-08 22:13:08 +0000644 .Case("pop", Is64Bit ? "popq" : "popl")
Dan Gohman29790ed2010-05-20 16:16:00 +0000645 .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
646 .Case("popf", Is64Bit ? "popfq" : "popfl")
Chris Lattnerb47c0422010-09-11 16:39:16 +0000647 .Case("pushfd", "pushfl")
648 .Case("popfd", "popfl")
Kevin Enderby7e7482c2010-05-21 23:01:38 +0000649 .Case("retl", Is64Bit ? "retl" : "ret")
650 .Case("retq", Is64Bit ? "ret" : "retq")
Chris Lattner3340c3e2010-09-11 17:06:05 +0000651 .Case("setz", "sete") .Case("setnz", "setne")
652 .Case("setc", "setb") .Case("setna", "setbe")
653 .Case("setnae", "setb").Case("setnb", "setae")
654 .Case("setnbe", "seta").Case("setnc", "setae")
655 .Case("setng", "setle").Case("setnge", "setl")
656 .Case("setnl", "setge").Case("setnle", "setg")
657 .Case("setpe", "setp") .Case("setpo", "setnp")
658 .Case("jz", "je") .Case("jnz", "jne")
659 .Case("jc", "jb") .Case("jna", "jbe")
660 .Case("jnae", "jb").Case("jnb", "jae")
661 .Case("jnbe", "ja").Case("jnc", "jae")
662 .Case("jng", "jle").Case("jnge", "jl")
663 .Case("jnl", "jge").Case("jnle", "jg")
664 .Case("jpe", "jp") .Case("jpo", "jnp")
Chris Lattner30bb3842010-09-07 00:05:45 +0000665 // Condition code aliases for 16-bit, 32-bit, 64-bit and unspec operands.
666 .Case("cmovcw", "cmovbw") .Case("cmovcl", "cmovbl")
667 .Case("cmovcq", "cmovbq") .Case("cmovc", "cmovb")
Chris Lattner1bbb14a2010-09-11 17:08:22 +0000668 .Case("cmovnaew","cmovbw") .Case("cmovnael","cmovbl")
669 .Case("cmovnaeq","cmovbq") .Case("cmovnae", "cmovb")
Chris Lattner30bb3842010-09-07 00:05:45 +0000670 .Case("cmovnaw", "cmovbew").Case("cmovnal", "cmovbel")
671 .Case("cmovnaq", "cmovbeq").Case("cmovna", "cmovbe")
672 .Case("cmovnbw", "cmovaew").Case("cmovnbl", "cmovael")
673 .Case("cmovnbq", "cmovaeq").Case("cmovnb", "cmovae")
674 .Case("cmovnbew","cmovaw") .Case("cmovnbel","cmoval")
675 .Case("cmovnbeq","cmovaq") .Case("cmovnbe", "cmova")
676 .Case("cmovncw", "cmovaew").Case("cmovncl", "cmovael")
677 .Case("cmovncq", "cmovaeq").Case("cmovnc", "cmovae")
678 .Case("cmovngw", "cmovlew").Case("cmovngl", "cmovlel")
679 .Case("cmovngq", "cmovleq").Case("cmovng", "cmovle")
680 .Case("cmovnw", "cmovgew").Case("cmovnl", "cmovgel")
681 .Case("cmovnq", "cmovgeq").Case("cmovn", "cmovge")
682 .Case("cmovngw", "cmovlew").Case("cmovngl", "cmovlel")
683 .Case("cmovngq", "cmovleq").Case("cmovng", "cmovle")
684 .Case("cmovngew","cmovlw") .Case("cmovngel","cmovll")
685 .Case("cmovngeq","cmovlq") .Case("cmovnge", "cmovl")
686 .Case("cmovnlw", "cmovgew").Case("cmovnll", "cmovgel")
687 .Case("cmovnlq", "cmovgeq").Case("cmovnl", "cmovge")
688 .Case("cmovnlew","cmovgw") .Case("cmovnlel","cmovgl")
689 .Case("cmovnleq","cmovgq") .Case("cmovnle", "cmovg")
690 .Case("cmovnzw", "cmovnew").Case("cmovnzl", "cmovnel")
691 .Case("cmovnzq", "cmovneq").Case("cmovnz", "cmovne")
692 .Case("cmovzw", "cmovew") .Case("cmovzl", "cmovel")
693 .Case("cmovzq", "cmoveq") .Case("cmovz", "cmove")
Chris Lattner9dfd2e32010-09-22 04:56:20 +0000694 // Floating point stack cmov aliases.
695 .Case("fcmovz", "fcmove")
696 .Case("fcmova", "fcmovnbe")
697 .Case("fcmovnae", "fcmovb")
698 .Case("fcmovna", "fcmovbe")
699 .Case("fcmovae", "fcmovnb")
Kevin Enderbyb2922892010-05-28 20:59:10 +0000700 .Case("fwait", "wait")
Chris Lattner74d320d2010-09-16 20:46:38 +0000701 .Case("movzx", "movzb") // FIXME: Not correct.
702 .Case("fildq", "fildll")
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000703 .Default(Name);
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000704
705 // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
706 const MCExpr *ExtraImmOp = 0;
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000707 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000708 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
709 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000710 bool IsVCMP = PatchedName.startswith("vcmp");
711 unsigned SSECCIdx = IsVCMP ? 4 : 3;
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000712 unsigned SSEComparisonCode = StringSwitch<unsigned>(
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000713 PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
Bruno Cardoso Lopes6c614512010-07-07 22:24:03 +0000714 .Case("eq", 0)
715 .Case("lt", 1)
716 .Case("le", 2)
717 .Case("unord", 3)
718 .Case("neq", 4)
719 .Case("nlt", 5)
720 .Case("nle", 6)
721 .Case("ord", 7)
722 .Case("eq_uq", 8)
723 .Case("nge", 9)
724 .Case("ngt", 0x0A)
725 .Case("false", 0x0B)
726 .Case("neq_oq", 0x0C)
727 .Case("ge", 0x0D)
728 .Case("gt", 0x0E)
729 .Case("true", 0x0F)
730 .Case("eq_os", 0x10)
731 .Case("lt_oq", 0x11)
732 .Case("le_oq", 0x12)
733 .Case("unord_s", 0x13)
734 .Case("neq_us", 0x14)
735 .Case("nlt_uq", 0x15)
736 .Case("nle_uq", 0x16)
737 .Case("ord_s", 0x17)
738 .Case("eq_us", 0x18)
739 .Case("nge_uq", 0x19)
740 .Case("ngt_uq", 0x1A)
741 .Case("false_os", 0x1B)
742 .Case("neq_os", 0x1C)
743 .Case("ge_oq", 0x1D)
744 .Case("gt_oq", 0x1E)
745 .Case("true_us", 0x1F)
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000746 .Default(~0U);
747 if (SSEComparisonCode != ~0U) {
748 ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode,
749 getParser().getContext());
750 if (PatchedName.endswith("ss")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000751 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000752 } else if (PatchedName.endswith("sd")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000753 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000754 } else if (PatchedName.endswith("ps")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000755 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000756 } else {
757 assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000758 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000759 }
760 }
761 }
Bruno Cardoso Lopesea0e05a2010-07-23 18:41:12 +0000762
763 // FIXME: Hack to recognize vpclmul<src1_quadword, src2_quadword>dq
764 if (PatchedName.startswith("vpclmul")) {
765 unsigned CLMULQuadWordSelect = StringSwitch<unsigned>(
766 PatchedName.slice(7, PatchedName.size() - 2))
767 .Case("lqlq", 0x00) // src1[63:0], src2[63:0]
768 .Case("hqlq", 0x01) // src1[127:64], src2[63:0]
769 .Case("lqhq", 0x10) // src1[63:0], src2[127:64]
770 .Case("hqhq", 0x11) // src1[127:64], src2[127:64]
771 .Default(~0U);
772 if (CLMULQuadWordSelect != ~0U) {
773 ExtraImmOp = MCConstantExpr::Create(CLMULQuadWordSelect,
774 getParser().getContext());
775 assert(PatchedName.endswith("dq") && "Unexpected mnemonic!");
776 PatchedName = "vpclmulqdq";
777 }
778 }
Chris Lattner8caea682010-09-08 04:53:27 +0000779
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000780 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000781
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000782 if (ExtraImmOp)
783 Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
Chris Lattner4cfbcdc2010-09-06 18:32:06 +0000784
Chris Lattner086a83a2010-09-08 05:17:37 +0000785
786 // Determine whether this is an instruction prefix.
787 bool isPrefix =
788 PatchedName == "lock" || PatchedName == "rep" ||
789 PatchedName == "repne";
790
791
792 // This does the actual operand parsing. Don't parse any more if we have a
793 // prefix juxtaposed with an operation like "lock incl 4(%rax)", because we
794 // just want to parse the "lock" as the first instruction and the "incl" as
795 // the next one.
796 if (getLexer().isNot(AsmToken::EndOfStatement) && !isPrefix) {
Daniel Dunbar71527c12009-08-11 05:00:25 +0000797
798 // Parse '*' modifier.
799 if (getLexer().is(AsmToken::Star)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000800 SMLoc Loc = Parser.getTok().getLoc();
Chris Lattner528d00b2010-01-15 19:28:38 +0000801 Operands.push_back(X86Operand::CreateToken("*", Loc));
Sean Callanana83fd7d2010-01-19 20:27:46 +0000802 Parser.Lex(); // Eat the star.
Daniel Dunbar71527c12009-08-11 05:00:25 +0000803 }
804
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000805 // Read the first operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000806 if (X86Operand *Op = ParseOperand())
807 Operands.push_back(Op);
Chris Lattnera2a9d162010-09-11 16:18:25 +0000808 else {
809 Parser.EatToEndOfStatement();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000810 return true;
Chris Lattnera2a9d162010-09-11 16:18:25 +0000811 }
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000812
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000813 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +0000814 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000815
816 // Parse and remember the operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000817 if (X86Operand *Op = ParseOperand())
818 Operands.push_back(Op);
Chris Lattnera2a9d162010-09-11 16:18:25 +0000819 else {
820 Parser.EatToEndOfStatement();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000821 return true;
Chris Lattnera2a9d162010-09-11 16:18:25 +0000822 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000823 }
Chris Lattner086a83a2010-09-08 05:17:37 +0000824
Chris Lattnera2a9d162010-09-11 16:18:25 +0000825 if (getLexer().isNot(AsmToken::EndOfStatement)) {
826 Parser.EatToEndOfStatement();
Chris Lattner086a83a2010-09-08 05:17:37 +0000827 return TokError("unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +0000828 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000829 }
Chris Lattner91689c12010-09-08 05:10:46 +0000830
Chris Lattner086a83a2010-09-08 05:17:37 +0000831 if (getLexer().is(AsmToken::EndOfStatement))
832 Parser.Lex(); // Consume the EndOfStatement
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000833
Chris Lattner4bd21712010-09-15 04:33:27 +0000834 // FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>. Canonicalize to
Chris Lattner30561ab2010-09-11 16:32:12 +0000835 // "shift <op>".
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000836 if ((Name.startswith("shr") || Name.startswith("sar") ||
837 Name.startswith("shl")) &&
Chris Lattner4cfbcdc2010-09-06 18:32:06 +0000838 Operands.size() == 3) {
839 X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]);
840 if (Op1->isImm() && isa<MCConstantExpr>(Op1->getImm()) &&
841 cast<MCConstantExpr>(Op1->getImm())->getValue() == 1) {
842 delete Operands[1];
843 Operands.erase(Operands.begin() + 1);
844 }
Daniel Dunbarfbd12cc2010-03-20 22:36:38 +0000845 }
Chris Lattner4bd21712010-09-15 04:33:27 +0000846
847 // FIXME: Hack to handle recognize "rc[lr] <op>" -> "rcl $1, <op>".
848 if ((Name.startswith("rcl") || Name.startswith("rcr")) &&
849 Operands.size() == 2) {
850 const MCExpr *One = MCConstantExpr::Create(1, getParser().getContext());
851 Operands.push_back(X86Operand::CreateImm(One, NameLoc, NameLoc));
852 std::swap(Operands[1], Operands[2]);
853 }
Chris Lattner6b40b0d2010-09-15 04:37:18 +0000854
855 // FIXME: Hack to handle recognize "sh[lr]d op,op" -> "shld $1, op,op".
856 if ((Name.startswith("shld") || Name.startswith("shrd")) &&
857 Operands.size() == 3) {
858 const MCExpr *One = MCConstantExpr::Create(1, getParser().getContext());
859 Operands.insert(Operands.begin()+1,
860 X86Operand::CreateImm(One, NameLoc, NameLoc));
861 }
862
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000863
Chris Lattner30561ab2010-09-11 16:32:12 +0000864 // FIXME: Hack to handle recognize "in[bwl] <op>". Canonicalize it to
865 // "inb <op>, %al".
866 if ((Name == "inb" || Name == "inw" || Name == "inl") &&
867 Operands.size() == 2) {
868 unsigned Reg;
869 if (Name[2] == 'b')
870 Reg = MatchRegisterName("al");
871 else if (Name[2] == 'w')
872 Reg = MatchRegisterName("ax");
873 else
874 Reg = MatchRegisterName("eax");
875 SMLoc Loc = Operands.back()->getEndLoc();
876 Operands.push_back(X86Operand::CreateReg(Reg, Loc, Loc));
877 }
878
879 // FIXME: Hack to handle recognize "out[bwl] <op>". Canonicalize it to
880 // "outb %al, <op>".
881 if ((Name == "outb" || Name == "outw" || Name == "outl") &&
882 Operands.size() == 2) {
883 unsigned Reg;
884 if (Name[3] == 'b')
885 Reg = MatchRegisterName("al");
886 else if (Name[3] == 'w')
887 Reg = MatchRegisterName("ax");
888 else
889 Reg = MatchRegisterName("eax");
890 SMLoc Loc = Operands.back()->getEndLoc();
891 Operands.push_back(X86Operand::CreateReg(Reg, Loc, Loc));
892 std::swap(Operands[1], Operands[2]);
893 }
894
Chris Lattner5f2311d2010-09-14 23:34:29 +0000895 // FIXME: Hack to handle "out[bwl]? %al, (%dx)" -> "outb %al, %dx".
896 if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") &&
897 Operands.size() == 3) {
898 X86Operand &Op = *(X86Operand*)Operands.back();
899 if (Op.isMem() && Op.Mem.SegReg == 0 &&
900 isa<MCConstantExpr>(Op.Mem.Disp) &&
901 cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 &&
902 Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
903 SMLoc Loc = Op.getEndLoc();
904 Operands.back() = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
905 delete &Op;
906 }
907 }
908
Kevin Enderby492d4f42010-05-25 20:52:34 +0000909 // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
910 // "f{mul*,add*,sub*,div*} $op"
911 if ((Name.startswith("fmul") || Name.startswith("fadd") ||
912 Name.startswith("fsub") || Name.startswith("fdiv")) &&
913 Operands.size() == 3 &&
914 static_cast<X86Operand*>(Operands[2])->isReg() &&
915 static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
916 delete Operands[2];
917 Operands.erase(Operands.begin() + 2);
918 }
Chris Lattnerff0062a2010-09-27 07:08:21 +0000919
920 // FIXME: Hack to handle "f{mulp,addp} st(0), $op" the same as
921 // "f{mulp,addp} $op", since they commute.
922 if ((Name == "fmulp" || Name == "faddp") && Operands.size() == 3 &&
Chris Lattner415624c2010-09-22 06:26:39 +0000923 static_cast<X86Operand*>(Operands[1])->isReg() &&
924 static_cast<X86Operand*>(Operands[1])->getReg() == X86::ST0) {
925 delete Operands[1];
926 Operands.erase(Operands.begin() + 1);
927 }
928
Daniel Dunbar1c8d7772010-08-24 19:37:56 +0000929 // FIXME: Hack to handle "imul <imm>, B" which is an alias for "imul <imm>, B,
930 // B".
Daniel Dunbar09392782010-08-24 19:24:18 +0000931 if (Name.startswith("imul") && Operands.size() == 3 &&
Daniel Dunbar1c8d7772010-08-24 19:37:56 +0000932 static_cast<X86Operand*>(Operands[1])->isImm() &&
Daniel Dunbar09392782010-08-24 19:24:18 +0000933 static_cast<X86Operand*>(Operands.back())->isReg()) {
934 X86Operand *Op = static_cast<X86Operand*>(Operands.back());
935 Operands.push_back(X86Operand::CreateReg(Op->getReg(), Op->getStartLoc(),
936 Op->getEndLoc()));
937 }
Chris Lattner7ece7162010-09-06 23:51:44 +0000938
939 // 'sldt <mem>' can be encoded with either sldtw or sldtq with the same
940 // effect (both store to a 16-bit mem). Force to sldtw to avoid ambiguity
941 // errors, since its encoding is the most compact.
942 if (Name == "sldt" && Operands.size() == 2 &&
Benjamin Kramer1ecb9782010-09-07 14:40:58 +0000943 static_cast<X86Operand*>(Operands[1])->isMem()) {
944 delete Operands[0];
Chris Lattner7ece7162010-09-06 23:51:44 +0000945 Operands[0] = X86Operand::CreateToken("sldtw", NameLoc);
Benjamin Kramer1ecb9782010-09-07 14:40:58 +0000946 }
Chris Lattner8caea682010-09-08 04:53:27 +0000947
948 // The assembler accepts "xchgX <reg>, <mem>" and "xchgX <mem>, <reg>" as
949 // synonyms. Our tables only have the "<reg>, <mem>" form, so if we see the
950 // other operand order, swap them.
Chris Lattner28a9c2f2010-09-08 22:27:05 +0000951 if (Name == "xchgb" || Name == "xchgw" || Name == "xchgl" || Name == "xchgq"||
952 Name == "xchg")
Chris Lattner8caea682010-09-08 04:53:27 +0000953 if (Operands.size() == 3 &&
954 static_cast<X86Operand*>(Operands[1])->isMem() &&
955 static_cast<X86Operand*>(Operands[2])->isReg()) {
956 std::swap(Operands[1], Operands[2]);
957 }
Daniel Dunbar09392782010-08-24 19:24:18 +0000958
Chris Lattner2907d2e2010-09-08 05:51:12 +0000959 // The assembler accepts "testX <reg>, <mem>" and "testX <mem>, <reg>" as
960 // synonyms. Our tables only have the "<mem>, <reg>" form, so if we see the
961 // other operand order, swap them.
Chris Lattner28a9c2f2010-09-08 22:27:05 +0000962 if (Name == "testb" || Name == "testw" || Name == "testl" || Name == "testq"||
963 Name == "test")
Chris Lattner2907d2e2010-09-08 05:51:12 +0000964 if (Operands.size() == 3 &&
965 static_cast<X86Operand*>(Operands[1])->isReg() &&
966 static_cast<X86Operand*>(Operands[2])->isMem()) {
967 std::swap(Operands[1], Operands[2]);
968 }
969
Chris Lattner4dbcba02010-09-15 04:04:33 +0000970 // The assembler accepts these instructions with no operand as a synonym for
971 // an instruction acting on st(1). e.g. "fxch" -> "fxch %st(1)".
972 if ((Name == "fxch" || Name == "fucom" || Name == "fucomp" ||
973 Name == "faddp" || Name == "fsubp" || Name == "fsubrp" ||
974 Name == "fmulp" || Name == "fdivp" || Name == "fdivrp") &&
975 Operands.size() == 1) {
976 Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(1)"),
977 NameLoc, NameLoc));
978 }
979
Chris Lattner7df35db2010-09-15 04:08:38 +0000980 // The assembler accepts these instructions with two few operands as a synonym
981 // for taking %st(1),%st(0) or X, %st(0).
982 if ((Name == "fcomi" || Name == "fucomi") && Operands.size() < 3) {
983 if (Operands.size() == 1)
984 Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(1)"),
985 NameLoc, NameLoc));
986 Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(0)"),
987 NameLoc, NameLoc));
988 }
Chris Lattner4dbcba02010-09-15 04:04:33 +0000989
Chris Lattner81ce1732010-09-15 04:15:16 +0000990 // The assembler accepts various amounts of brokenness for fnstsw.
991 if (Name == "fnstsw") {
992 if (Operands.size() == 2 &&
993 static_cast<X86Operand*>(Operands[1])->isReg()) {
994 // "fnstsw al" and "fnstsw eax" -> "fnstw"
995 unsigned Reg = static_cast<X86Operand*>(Operands[1])->Reg.RegNo;
996 if (Reg == MatchRegisterName("eax") ||
997 Reg == MatchRegisterName("al")) {
998 delete Operands[1];
999 Operands.pop_back();
1000 }
1001 }
1002
1003 // "fnstw" -> "fnstw %ax"
1004 if (Operands.size() == 1)
1005 Operands.push_back(X86Operand::CreateReg(MatchRegisterName("ax"),
1006 NameLoc, NameLoc));
1007 }
1008
Chris Lattner09bfe642010-09-15 05:25:21 +00001009 // jmp $42,$5 -> ljmp, similarly for call.
1010 if ((Name.startswith("call") || Name.startswith("jmp")) &&
1011 Operands.size() == 3 &&
1012 static_cast<X86Operand*>(Operands[1])->isImm() &&
1013 static_cast<X86Operand*>(Operands[2])->isImm()) {
1014 const char *NewOpName = StringSwitch<const char *>(Name)
1015 .Case("jmp", "ljmp")
1016 .Case("jmpw", "ljmpw")
1017 .Case("jmpl", "ljmpl")
1018 .Case("jmpq", "ljmpq")
1019 .Case("call", "lcall")
1020 .Case("callw", "lcallw")
1021 .Case("calll", "lcalll")
1022 .Case("callq", "lcallq")
1023 .Default(0);
1024 if (NewOpName) {
1025 delete Operands[0];
1026 Operands[0] = X86Operand::CreateToken(NewOpName, NameLoc);
Chris Lattneree7e6f42010-09-15 05:30:20 +00001027 Name = NewOpName;
Chris Lattner09bfe642010-09-15 05:25:21 +00001028 }
1029 }
1030
Chris Lattneree7e6f42010-09-15 05:30:20 +00001031 // lcall and ljmp -> lcalll and ljmpl
1032 if ((Name == "lcall" || Name == "ljmp") && Operands.size() == 3) {
1033 delete Operands[0];
1034 Operands[0] = X86Operand::CreateToken(Name == "lcall" ? "lcalll" : "ljmpl",
1035 NameLoc);
1036 }
1037
Chris Lattnerbd857252010-09-22 05:49:14 +00001038 // call foo is not ambiguous with callw.
1039 if (Name == "call" && Operands.size() == 2) {
1040 const char *NewName = Is64Bit ? "callq" : "calll";
1041 delete Operands[0];
1042 Operands[0] = X86Operand::CreateToken(NewName, NameLoc);
1043 Name = NewName;
1044 }
1045
Chris Lattnera91e5102010-09-22 03:50:32 +00001046 // movsd -> movsl (when no operands are specified).
1047 if (Name == "movsd" && Operands.size() == 1) {
1048 delete Operands[0];
1049 Operands[0] = X86Operand::CreateToken("movsl", NameLoc);
1050 }
1051
Chris Lattner39cf8de2010-09-22 04:04:03 +00001052 // fstp <mem> -> fstps <mem>. Without this, we'll default to fstpl due to
1053 // suffix searching.
1054 if (Name == "fstp" && Operands.size() == 2 &&
1055 static_cast<X86Operand*>(Operands[1])->isMem()) {
1056 delete Operands[0];
1057 Operands[0] = X86Operand::CreateToken("fstps", NameLoc);
1058 }
1059
Chris Lattner4f59cbf2010-09-27 04:23:03 +00001060
1061 // "clr <reg>" -> "xor <reg>, <reg>".
1062 if ((Name == "clrb" || Name == "clrw" || Name == "clrl" || Name == "clrq" ||
1063 Name == "clr") && Operands.size() == 2 &&
1064 static_cast<X86Operand*>(Operands[1])->isReg()) {
1065 unsigned RegNo = static_cast<X86Operand*>(Operands[1])->getReg();
1066 Operands.push_back(X86Operand::CreateReg(RegNo, NameLoc, NameLoc));
1067 delete Operands[0];
1068 Operands[0] = X86Operand::CreateToken("xor", NameLoc);
1069 }
1070
Chris Lattnerf29c0b62010-01-14 22:21:20 +00001071 return false;
Daniel Dunbar3c2a8932009-07-20 18:55:04 +00001072}
1073
Kevin Enderbyce4bec82009-09-10 20:51:44 +00001074bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
1075 StringRef IDVal = DirectiveID.getIdentifier();
1076 if (IDVal == ".word")
1077 return ParseDirectiveWord(2, DirectiveID.getLoc());
1078 return true;
1079}
1080
1081/// ParseDirectiveWord
1082/// ::= .word [ expression (, expression)* ]
1083bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
1084 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1085 for (;;) {
1086 const MCExpr *Value;
1087 if (getParser().ParseExpression(Value))
1088 return true;
1089
Chris Lattnerc35681b2010-01-19 19:46:13 +00001090 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
Kevin Enderbyce4bec82009-09-10 20:51:44 +00001091
1092 if (getLexer().is(AsmToken::EndOfStatement))
1093 break;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +00001094
Kevin Enderbyce4bec82009-09-10 20:51:44 +00001095 // FIXME: Improve diagnostic.
1096 if (getLexer().isNot(AsmToken::Comma))
1097 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +00001098 Parser.Lex();
Kevin Enderbyce4bec82009-09-10 20:51:44 +00001099 }
1100 }
1101
Sean Callanana83fd7d2010-01-19 20:27:46 +00001102 Parser.Lex();
Kevin Enderbyce4bec82009-09-10 20:51:44 +00001103 return false;
1104}
1105
Daniel Dunbar2ecc3bb2010-08-12 00:55:38 +00001106
Chris Lattner4dbcba02010-09-15 04:04:33 +00001107bool X86ATTAsmParser::
1108MatchInstruction(SMLoc IDLoc,
1109 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1110 MCInst &Inst) {
Daniel Dunbar2ecc3bb2010-08-12 00:55:38 +00001111 assert(!Operands.empty() && "Unexpect empty operand list!");
1112
Chris Lattner628fbec2010-09-06 21:54:15 +00001113 bool WasOriginallyInvalidOperand = false;
Chris Lattner339cc7b2010-09-06 22:11:18 +00001114 unsigned OrigErrorInfo;
Chris Lattner628fbec2010-09-06 21:54:15 +00001115
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001116 // First, try a direct match.
Chris Lattner339cc7b2010-09-06 22:11:18 +00001117 switch (MatchInstructionImpl(Operands, Inst, OrigErrorInfo)) {
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001118 case Match_Success:
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001119 return false;
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001120 case Match_MissingFeature:
1121 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1122 return true;
Chris Lattner628fbec2010-09-06 21:54:15 +00001123 case Match_InvalidOperand:
1124 WasOriginallyInvalidOperand = true;
1125 break;
1126 case Match_MnemonicFail:
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001127 break;
1128 }
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001129
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001130 // FIXME: Ideally, we would only attempt suffix matches for things which are
1131 // valid prefixes, and we could just infer the right unambiguous
1132 // type. However, that requires substantially more matcher support than the
1133 // following hack.
1134
Chris Lattner3e4582a2010-09-06 19:11:01 +00001135 X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
1136 assert(Op->isToken() && "Leading operand should always be a mnemonic!");
1137
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001138 // Change the operand to point to a temporary token.
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001139 StringRef Base = Op->getToken();
Daniel Dunbar2ecc3bb2010-08-12 00:55:38 +00001140 SmallString<16> Tmp;
1141 Tmp += Base;
1142 Tmp += ' ';
1143 Op->setTokenValue(Tmp.str());
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001144
1145 // Check for the various suffix matches.
1146 Tmp[Base.size()] = 'b';
Chris Lattner339cc7b2010-09-06 22:11:18 +00001147 unsigned BErrorInfo, WErrorInfo, LErrorInfo, QErrorInfo;
1148 MatchResultTy MatchB = MatchInstructionImpl(Operands, Inst, BErrorInfo);
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001149 Tmp[Base.size()] = 'w';
Chris Lattner339cc7b2010-09-06 22:11:18 +00001150 MatchResultTy MatchW = MatchInstructionImpl(Operands, Inst, WErrorInfo);
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001151 Tmp[Base.size()] = 'l';
Chris Lattner339cc7b2010-09-06 22:11:18 +00001152 MatchResultTy MatchL = MatchInstructionImpl(Operands, Inst, LErrorInfo);
Daniel Dunbar059379a2010-05-12 00:54:20 +00001153 Tmp[Base.size()] = 'q';
Chris Lattner339cc7b2010-09-06 22:11:18 +00001154 MatchResultTy MatchQ = MatchInstructionImpl(Operands, Inst, QErrorInfo);
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001155
1156 // Restore the old token.
1157 Op->setTokenValue(Base);
1158
1159 // If exactly one matched, then we treat that as a successful match (and the
1160 // instruction will already have been filled in correctly, since the failing
1161 // matches won't have modified it).
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001162 unsigned NumSuccessfulMatches =
1163 (MatchB == Match_Success) + (MatchW == Match_Success) +
1164 (MatchL == Match_Success) + (MatchQ == Match_Success);
1165 if (NumSuccessfulMatches == 1)
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001166 return false;
1167
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001168 // Otherwise, the match failed, try to produce a decent error message.
Daniel Dunbar2ecc3bb2010-08-12 00:55:38 +00001169
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001170 // If we had multiple suffix matches, then identify this as an ambiguous
1171 // match.
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001172 if (NumSuccessfulMatches > 1) {
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001173 char MatchChars[4];
1174 unsigned NumMatches = 0;
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001175 if (MatchB == Match_Success)
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001176 MatchChars[NumMatches++] = 'b';
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001177 if (MatchW == Match_Success)
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001178 MatchChars[NumMatches++] = 'w';
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001179 if (MatchL == Match_Success)
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001180 MatchChars[NumMatches++] = 'l';
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001181 if (MatchQ == Match_Success)
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001182 MatchChars[NumMatches++] = 'q';
1183
1184 SmallString<126> Msg;
1185 raw_svector_ostream OS(Msg);
1186 OS << "ambiguous instructions require an explicit suffix (could be ";
1187 for (unsigned i = 0; i != NumMatches; ++i) {
1188 if (i != 0)
1189 OS << ", ";
1190 if (i + 1 == NumMatches)
1191 OS << "or ";
1192 OS << "'" << Base << MatchChars[i] << "'";
1193 }
1194 OS << ")";
1195 Error(IDLoc, OS.str());
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001196 return true;
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001197 }
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001198
Chris Lattner628fbec2010-09-06 21:54:15 +00001199 // Okay, we know that none of the variants matched successfully.
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001200
Chris Lattner628fbec2010-09-06 21:54:15 +00001201 // If all of the instructions reported an invalid mnemonic, then the original
1202 // mnemonic was invalid.
1203 if ((MatchB == Match_MnemonicFail) && (MatchW == Match_MnemonicFail) &&
1204 (MatchL == Match_MnemonicFail) && (MatchQ == Match_MnemonicFail)) {
Chris Lattner339cc7b2010-09-06 22:11:18 +00001205 if (!WasOriginallyInvalidOperand) {
Chris Lattner628fbec2010-09-06 21:54:15 +00001206 Error(IDLoc, "invalid instruction mnemonic '" + Base + "'");
Chris Lattner339cc7b2010-09-06 22:11:18 +00001207 return true;
1208 }
1209
1210 // Recover location info for the operand if we know which was the problem.
1211 SMLoc ErrorLoc = IDLoc;
1212 if (OrigErrorInfo != ~0U) {
Chris Lattnerd28452d2010-09-15 03:50:11 +00001213 if (OrigErrorInfo >= Operands.size())
1214 return Error(IDLoc, "too few operands for instruction");
1215
Chris Lattner339cc7b2010-09-06 22:11:18 +00001216 ErrorLoc = ((X86Operand*)Operands[OrigErrorInfo])->getStartLoc();
1217 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
1218 }
1219
Chris Lattnerd28452d2010-09-15 03:50:11 +00001220 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner628fbec2010-09-06 21:54:15 +00001221 }
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001222
1223 // If one instruction matched with a missing feature, report this as a
1224 // missing feature.
1225 if ((MatchB == Match_MissingFeature) + (MatchW == Match_MissingFeature) +
Chris Lattner628fbec2010-09-06 21:54:15 +00001226 (MatchL == Match_MissingFeature) + (MatchQ == Match_MissingFeature) == 1){
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001227 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1228 return true;
1229 }
1230
Chris Lattner628fbec2010-09-06 21:54:15 +00001231 // If one instruction matched with an invalid operand, report this as an
1232 // operand failure.
1233 if ((MatchB == Match_InvalidOperand) + (MatchW == Match_InvalidOperand) +
1234 (MatchL == Match_InvalidOperand) + (MatchQ == Match_InvalidOperand) == 1){
1235 Error(IDLoc, "invalid operand for instruction");
1236 return true;
1237 }
1238
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001239 // If all of these were an outright failure, report it in a useless way.
1240 // FIXME: We should give nicer diagnostics about the exact failure.
Chris Lattner628fbec2010-09-06 21:54:15 +00001241 Error(IDLoc, "unknown use of instruction mnemonic without a size suffix");
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001242 return true;
1243}
1244
1245
Sean Callanan5051cb82010-01-23 02:43:15 +00001246extern "C" void LLVMInitializeX86AsmLexer();
1247
Daniel Dunbar71475772009-07-17 20:42:00 +00001248// Force static initialization.
1249extern "C" void LLVMInitializeX86AsmParser() {
Daniel Dunbar63ec0932010-03-18 20:06:02 +00001250 RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
1251 RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
Sean Callanan5051cb82010-01-23 02:43:15 +00001252 LLVMInitializeX86AsmLexer();
Daniel Dunbar71475772009-07-17 20:42:00 +00001253}
Daniel Dunbar00331992009-07-29 00:02:19 +00001254
Chris Lattner3e4582a2010-09-06 19:11:01 +00001255#define GET_REGISTER_MATCHER
1256#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar00331992009-07-29 00:02:19 +00001257#include "X86GenAsmMatcher.inc"