blob: 7098c58cde933afdd7face3ab0a1c010834df66b [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"
Daniel Dunbar2ecc3bb2010-08-12 00:55:38 +000013#include "llvm/ADT/SmallString.h"
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +000014#include "llvm/ADT/SmallVector.h"
Daniel Dunbar3e0c9792010-02-10 21:19:28 +000015#include "llvm/ADT/StringSwitch.h"
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000016#include "llvm/ADT/Twine.h"
Kevin Enderbyce4bec82009-09-10 20:51:44 +000017#include "llvm/MC/MCStreamer.h"
Daniel Dunbar73da11e2009-08-31 08:08:38 +000018#include "llvm/MC/MCExpr.h"
Daniel Dunbarb6d6aa22009-07-31 02:32:59 +000019#include "llvm/MC/MCInst.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000020#include "llvm/MC/MCParser/MCAsmLexer.h"
21#include "llvm/MC/MCParser/MCAsmParser.h"
22#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000023#include "llvm/Support/SourceMgr.h"
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +000024#include "llvm/Support/raw_ostream.h"
Daniel Dunbar71475772009-07-17 20:42:00 +000025#include "llvm/Target/TargetRegistry.h"
26#include "llvm/Target/TargetAsmParser.h"
27using namespace llvm;
28
29namespace {
Benjamin Kramerb60210e2009-07-31 11:35:26 +000030struct X86Operand;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000031
32class X86ATTAsmParser : public TargetAsmParser {
33 MCAsmParser &Parser;
Daniel Dunbar419197c2010-07-19 00:33:49 +000034 TargetMachine &TM;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000035
Daniel Dunbar63ec0932010-03-18 20:06:02 +000036protected:
37 unsigned Is64Bit : 1;
38
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000039private:
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000040 MCAsmParser &getParser() const { return Parser; }
41
42 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
43
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000044 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
45
Chris Lattner0c2538f2010-01-15 18:51:29 +000046 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000047
Chris Lattnera2bbb7c2010-01-15 18:44:13 +000048 X86Operand *ParseOperand();
Chris Lattnerb9270732010-04-17 18:56:34 +000049 X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
Kevin Enderbyce4bec82009-09-10 20:51:44 +000050
51 bool ParseDirectiveWord(unsigned Size, SMLoc L);
52
Daniel Dunbar2ecc3bb2010-08-12 00:55:38 +000053 bool MatchInstruction(SMLoc IDLoc,
54 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbare10787e2009-08-07 08:26:05 +000055 MCInst &Inst);
56
Daniel Dunbareefe8612010-07-19 05:44:09 +000057 /// @name Auto-generated Matcher Functions
58 /// {
Chris Lattner3e4582a2010-09-06 19:11:01 +000059
60#define GET_ASSEMBLER_HEADER
61#include "X86GenAsmMatcher.inc"
62
Daniel Dunbar00331992009-07-29 00:02:19 +000063 /// }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000064
65public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000066 X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
Daniel Dunbareefe8612010-07-19 05:44:09 +000067 : TargetAsmParser(T), Parser(_Parser), TM(TM) {
68
69 // Initialize the set of available features.
70 setAvailableFeatures(ComputeAvailableFeatures(
71 &TM.getSubtarget<X86Subtarget>()));
72 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000073
Benjamin Kramer92d89982010-07-14 22:38:02 +000074 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattnerf29c0b62010-01-14 22:21:20 +000075 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderbyce4bec82009-09-10 20:51:44 +000076
77 virtual bool ParseDirective(AsmToken DirectiveID);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000078};
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +000079
Daniel Dunbar63ec0932010-03-18 20:06:02 +000080class X86_32ATTAsmParser : public X86ATTAsmParser {
81public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000082 X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
83 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbar63ec0932010-03-18 20:06:02 +000084 Is64Bit = false;
85 }
86};
87
88class X86_64ATTAsmParser : public X86ATTAsmParser {
89public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000090 X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
91 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbar63ec0932010-03-18 20:06:02 +000092 Is64Bit = true;
93 }
94};
95
Chris Lattner4eb9df02009-07-29 06:33:53 +000096} // end anonymous namespace
97
Sean Callanan86c11812010-01-23 00:40:33 +000098/// @name Auto-generated Match Functions
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +000099/// {
Sean Callanan86c11812010-01-23 00:40:33 +0000100
Chris Lattner60db0a62010-02-09 00:34:28 +0000101static unsigned MatchRegisterName(StringRef Name);
Sean Callanan86c11812010-01-23 00:40:33 +0000102
103/// }
Chris Lattner4eb9df02009-07-29 06:33:53 +0000104
105namespace {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000106
107/// X86Operand - Instances of this class represent a parsed X86 machine
108/// instruction.
Chris Lattner872501b2010-01-14 21:20:55 +0000109struct X86Operand : public MCParsedAsmOperand {
Chris Lattner86e61532010-01-15 19:06:59 +0000110 enum KindTy {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000111 Token,
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000112 Register,
113 Immediate,
114 Memory
115 } Kind;
116
Chris Lattner0c2538f2010-01-15 18:51:29 +0000117 SMLoc StartLoc, EndLoc;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000118
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000119 union {
120 struct {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000121 const char *Data;
122 unsigned Length;
123 } Tok;
124
125 struct {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000126 unsigned RegNo;
127 } Reg;
128
129 struct {
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000130 const MCExpr *Val;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000131 } Imm;
132
133 struct {
134 unsigned SegReg;
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000135 const MCExpr *Disp;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000136 unsigned BaseReg;
137 unsigned IndexReg;
138 unsigned Scale;
139 } Mem;
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +0000140 };
Daniel Dunbar71475772009-07-17 20:42:00 +0000141
Chris Lattner015cfb12010-01-15 19:33:43 +0000142 X86Operand(KindTy K, SMLoc Start, SMLoc End)
Chris Lattner86e61532010-01-15 19:06:59 +0000143 : Kind(K), StartLoc(Start), EndLoc(End) {}
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000144
Chris Lattner86e61532010-01-15 19:06:59 +0000145 /// getStartLoc - Get the location of the first token of this operand.
146 SMLoc getStartLoc() const { return StartLoc; }
147 /// getEndLoc - Get the location of the last token of this operand.
148 SMLoc getEndLoc() const { return EndLoc; }
149
Daniel Dunbarebace222010-08-11 06:37:04 +0000150 virtual void dump(raw_ostream &OS) const {}
151
Daniel Dunbare10787e2009-08-07 08:26:05 +0000152 StringRef getToken() const {
153 assert(Kind == Token && "Invalid access!");
154 return StringRef(Tok.Data, Tok.Length);
155 }
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000156 void setTokenValue(StringRef Value) {
157 assert(Kind == Token && "Invalid access!");
158 Tok.Data = Value.data();
159 Tok.Length = Value.size();
160 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000161
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000162 unsigned getReg() const {
163 assert(Kind == Register && "Invalid access!");
164 return Reg.RegNo;
165 }
Daniel Dunbarf59ee962009-07-28 20:47:52 +0000166
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000167 const MCExpr *getImm() const {
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000168 assert(Kind == Immediate && "Invalid access!");
169 return Imm.Val;
170 }
171
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000172 const MCExpr *getMemDisp() const {
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000173 assert(Kind == Memory && "Invalid access!");
174 return Mem.Disp;
175 }
176 unsigned getMemSegReg() const {
177 assert(Kind == Memory && "Invalid access!");
178 return Mem.SegReg;
179 }
180 unsigned getMemBaseReg() const {
181 assert(Kind == Memory && "Invalid access!");
182 return Mem.BaseReg;
183 }
184 unsigned getMemIndexReg() const {
185 assert(Kind == Memory && "Invalid access!");
186 return Mem.IndexReg;
187 }
188 unsigned getMemScale() const {
189 assert(Kind == Memory && "Invalid access!");
190 return Mem.Scale;
191 }
192
Daniel Dunbar541efcc2009-08-08 07:50:56 +0000193 bool isToken() const {return Kind == Token; }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000194
195 bool isImm() const { return Kind == Immediate; }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000196
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000197 bool isImmSExti16i8() const {
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000198 if (!isImm())
199 return false;
200
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000201 // If this isn't a constant expr, just assume it fits and let relaxation
202 // handle it.
203 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
204 if (!CE)
205 return true;
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000206
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000207 // Otherwise, check the value is in a range that makes sense for this
208 // extension.
209 uint64_t Value = CE->getValue();
210 return (( Value <= 0x000000000000007FULL)||
211 (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)||
212 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000213 }
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000214 bool isImmSExti32i8() const {
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000215 if (!isImm())
216 return false;
217
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000218 // If this isn't a constant expr, just assume it fits and let relaxation
219 // handle it.
220 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
221 if (!CE)
222 return true;
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000223
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000224 // Otherwise, check the value is in a range that makes sense for this
225 // extension.
226 uint64_t Value = CE->getValue();
227 return (( Value <= 0x000000000000007FULL)||
228 (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
229 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
230 }
231 bool isImmSExti64i8() const {
232 if (!isImm())
233 return false;
234
235 // If this isn't a constant expr, just assume it fits and let relaxation
236 // handle it.
237 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
238 if (!CE)
239 return true;
240
241 // Otherwise, check the value is in a range that makes sense for this
242 // extension.
243 uint64_t Value = CE->getValue();
244 return (( Value <= 0x000000000000007FULL)||
245 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
246 }
247 bool isImmSExti64i32() const {
248 if (!isImm())
249 return false;
250
251 // If this isn't a constant expr, just assume it fits and let relaxation
252 // handle it.
253 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
254 if (!CE)
255 return true;
256
257 // Otherwise, check the value is in a range that makes sense for this
258 // extension.
259 uint64_t Value = CE->getValue();
260 return (( Value <= 0x000000007FFFFFFFULL)||
261 (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000262 }
263
Daniel Dunbare10787e2009-08-07 08:26:05 +0000264 bool isMem() const { return Kind == Memory; }
265
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000266 bool isAbsMem() const {
267 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
Daniel Dunbar3184f222010-02-02 21:44:16 +0000268 !getMemIndexReg() && getMemScale() == 1;
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000269 }
270
Daniel Dunbare10787e2009-08-07 08:26:05 +0000271 bool isReg() const { return Kind == Register; }
272
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000273 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
274 // Add as immediates when possible.
275 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
276 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
277 else
278 Inst.addOperand(MCOperand::CreateExpr(Expr));
279 }
280
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000281 void addRegOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000282 assert(N == 1 && "Invalid number of operands!");
283 Inst.addOperand(MCOperand::CreateReg(getReg()));
284 }
285
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000286 void addImmOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000287 assert(N == 1 && "Invalid number of operands!");
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000288 addExpr(Inst, getImm());
Daniel Dunbare10787e2009-08-07 08:26:05 +0000289 }
290
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000291 void addMemOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbara97adee2010-01-30 00:24:00 +0000292 assert((N == 5) && "Invalid number of operands!");
Daniel Dunbare10787e2009-08-07 08:26:05 +0000293 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
294 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
295 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000296 addExpr(Inst, getMemDisp());
Daniel Dunbara97adee2010-01-30 00:24:00 +0000297 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
298 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000299
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000300 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
301 assert((N == 1) && "Invalid number of operands!");
302 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
303 }
304
Chris Lattner528d00b2010-01-15 19:28:38 +0000305 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
306 X86Operand *Res = new X86Operand(Token, Loc, Loc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000307 Res->Tok.Data = Str.data();
308 Res->Tok.Length = Str.size();
Daniel Dunbare10787e2009-08-07 08:26:05 +0000309 return Res;
310 }
311
Chris Lattner0c2538f2010-01-15 18:51:29 +0000312 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
Chris Lattner86e61532010-01-15 19:06:59 +0000313 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000314 Res->Reg.RegNo = RegNo;
Chris Lattner0c2538f2010-01-15 18:51:29 +0000315 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000316 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000317
Chris Lattner528d00b2010-01-15 19:28:38 +0000318 static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
319 X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000320 Res->Imm.Val = Val;
321 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000322 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000323
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000324 /// Create an absolute memory operand.
325 static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
326 SMLoc EndLoc) {
327 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
328 Res->Mem.SegReg = 0;
329 Res->Mem.Disp = Disp;
330 Res->Mem.BaseReg = 0;
331 Res->Mem.IndexReg = 0;
Daniel Dunbar3184f222010-02-02 21:44:16 +0000332 Res->Mem.Scale = 1;
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000333 return Res;
334 }
335
336 /// Create a generalized memory operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000337 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
338 unsigned BaseReg, unsigned IndexReg,
Chris Lattner015cfb12010-01-15 19:33:43 +0000339 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000340 // We should never just have a displacement, that should be parsed as an
341 // absolute memory operand.
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000342 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
343
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000344 // The scale should always be one of {1,2,4,8}.
345 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000346 "Invalid scale!");
Chris Lattner015cfb12010-01-15 19:33:43 +0000347 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000348 Res->Mem.SegReg = SegReg;
349 Res->Mem.Disp = Disp;
350 Res->Mem.BaseReg = BaseReg;
351 Res->Mem.IndexReg = IndexReg;
352 Res->Mem.Scale = Scale;
353 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000354 }
355};
Daniel Dunbar3c2a8932009-07-20 18:55:04 +0000356
Chris Lattner4eb9df02009-07-29 06:33:53 +0000357} // end anonymous namespace.
Daniel Dunbarf59ee962009-07-28 20:47:52 +0000358
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000359
Chris Lattner0c2538f2010-01-15 18:51:29 +0000360bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
361 SMLoc &StartLoc, SMLoc &EndLoc) {
Chris Lattnercc2ad082010-01-15 18:27:19 +0000362 RegNo = 0;
Sean Callanan936b0d32010-01-19 21:44:56 +0000363 const AsmToken &TokPercent = Parser.getTok();
Kevin Enderby7d912182009-09-03 17:15:07 +0000364 assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
Chris Lattner0c2538f2010-01-15 18:51:29 +0000365 StartLoc = TokPercent.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000366 Parser.Lex(); // Eat percent token.
Kevin Enderby7d912182009-09-03 17:15:07 +0000367
Sean Callanan936b0d32010-01-19 21:44:56 +0000368 const AsmToken &Tok = Parser.getTok();
Kevin Enderbyc0edda32009-09-16 17:18:29 +0000369 if (Tok.isNot(AsmToken::Identifier))
370 return Error(Tok.getLoc(), "invalid register name");
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000371
Daniel Dunbar00331992009-07-29 00:02:19 +0000372 // FIXME: Validate register for the current architecture; we have to do
373 // validation later, so maybe there is no need for this here.
Kevin Enderby7d912182009-09-03 17:15:07 +0000374 RegNo = MatchRegisterName(Tok.getString());
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000375
Bruno Cardoso Lopes306a1f92010-07-24 00:06:39 +0000376 // FIXME: This should be done using Requires<In32BitMode> and
377 // Requires<In64BitMode> so "eiz" usage in 64-bit instructions
378 // can be also checked.
379 if (RegNo == X86::RIZ && !Is64Bit)
380 return Error(Tok.getLoc(), "riz register in 64-bit mode only");
381
Chris Lattnerd00faaa2010-02-09 00:49:22 +0000382 // Parse %st(1) and "%st" as "%st(0)"
383 if (RegNo == 0 && Tok.getString() == "st") {
384 RegNo = X86::ST0;
385 EndLoc = Tok.getLoc();
386 Parser.Lex(); // Eat 'st'
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000387
Chris Lattnerd00faaa2010-02-09 00:49:22 +0000388 // Check to see if we have '(4)' after %st.
389 if (getLexer().isNot(AsmToken::LParen))
390 return false;
391 // Lex the paren.
392 getParser().Lex();
393
394 const AsmToken &IntTok = Parser.getTok();
395 if (IntTok.isNot(AsmToken::Integer))
396 return Error(IntTok.getLoc(), "expected stack index");
397 switch (IntTok.getIntVal()) {
398 case 0: RegNo = X86::ST0; break;
399 case 1: RegNo = X86::ST1; break;
400 case 2: RegNo = X86::ST2; break;
401 case 3: RegNo = X86::ST3; break;
402 case 4: RegNo = X86::ST4; break;
403 case 5: RegNo = X86::ST5; break;
404 case 6: RegNo = X86::ST6; break;
405 case 7: RegNo = X86::ST7; break;
406 default: return Error(IntTok.getLoc(), "invalid stack index");
407 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000408
Chris Lattnerd00faaa2010-02-09 00:49:22 +0000409 if (getParser().Lex().isNot(AsmToken::RParen))
410 return Error(Parser.getTok().getLoc(), "expected ')'");
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000411
Chris Lattnerd00faaa2010-02-09 00:49:22 +0000412 EndLoc = Tok.getLoc();
413 Parser.Lex(); // Eat ')'
414 return false;
415 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000416
Chris Lattner80486622010-06-24 07:29:18 +0000417 // If this is "db[0-7]", match it as an alias
418 // for dr[0-7].
419 if (RegNo == 0 && Tok.getString().size() == 3 &&
420 Tok.getString().startswith("db")) {
421 switch (Tok.getString()[2]) {
422 case '0': RegNo = X86::DR0; break;
423 case '1': RegNo = X86::DR1; break;
424 case '2': RegNo = X86::DR2; break;
425 case '3': RegNo = X86::DR3; break;
426 case '4': RegNo = X86::DR4; break;
427 case '5': RegNo = X86::DR5; break;
428 case '6': RegNo = X86::DR6; break;
429 case '7': RegNo = X86::DR7; break;
430 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000431
Chris Lattner80486622010-06-24 07:29:18 +0000432 if (RegNo != 0) {
433 EndLoc = Tok.getLoc();
434 Parser.Lex(); // Eat it.
435 return false;
436 }
437 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000438
Daniel Dunbar66f4f542009-08-08 21:22:41 +0000439 if (RegNo == 0)
Daniel Dunbar00331992009-07-29 00:02:19 +0000440 return Error(Tok.getLoc(), "invalid register name");
441
Chris Lattner0c2538f2010-01-15 18:51:29 +0000442 EndLoc = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000443 Parser.Lex(); // Eat identifier token.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000444 return false;
Daniel Dunbar71475772009-07-17 20:42:00 +0000445}
446
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000447X86Operand *X86ATTAsmParser::ParseOperand() {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000448 switch (getLexer().getKind()) {
449 default:
Chris Lattnerb9270732010-04-17 18:56:34 +0000450 // Parse a memory operand with no segment register.
451 return ParseMemOperand(0, Parser.getTok().getLoc());
Chris Lattnercc2ad082010-01-15 18:27:19 +0000452 case AsmToken::Percent: {
Chris Lattnerb9270732010-04-17 18:56:34 +0000453 // Read the register.
Chris Lattnercc2ad082010-01-15 18:27:19 +0000454 unsigned RegNo;
Chris Lattner0c2538f2010-01-15 18:51:29 +0000455 SMLoc Start, End;
456 if (ParseRegister(RegNo, Start, End)) return 0;
Bruno Cardoso Lopes306a1f92010-07-24 00:06:39 +0000457 if (RegNo == X86::EIZ || RegNo == X86::RIZ) {
458 Error(Start, "eiz and riz can only be used as index registers");
459 return 0;
460 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000461
Chris Lattnerb9270732010-04-17 18:56:34 +0000462 // If this is a segment register followed by a ':', then this is the start
463 // of a memory reference, otherwise this is a normal register reference.
464 if (getLexer().isNot(AsmToken::Colon))
465 return X86Operand::CreateReg(RegNo, Start, End);
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000466
467
Chris Lattnerb9270732010-04-17 18:56:34 +0000468 getParser().Lex(); // Eat the colon.
469 return ParseMemOperand(RegNo, Start);
Chris Lattnercc2ad082010-01-15 18:27:19 +0000470 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000471 case AsmToken::Dollar: {
472 // $42 -> immediate.
Sean Callanan936b0d32010-01-19 21:44:56 +0000473 SMLoc Start = Parser.getTok().getLoc(), End;
Sean Callanana83fd7d2010-01-19 20:27:46 +0000474 Parser.Lex();
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000475 const MCExpr *Val;
Chris Lattnere17df0b2010-01-15 19:39:23 +0000476 if (getParser().ParseExpression(Val, End))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000477 return 0;
Chris Lattner528d00b2010-01-15 19:28:38 +0000478 return X86Operand::CreateImm(Val, Start, End);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000479 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000480 }
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +0000481}
482
Chris Lattnerb9270732010-04-17 18:56:34 +0000483/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
484/// has already been parsed if present.
485X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000486
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000487 // We have to disambiguate a parenthesized expression "(4+5)" from the start
488 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
Chris Lattner807a3bc2010-01-24 01:07:33 +0000489 // only way to do this without lookahead is to eat the '(' and see what is
490 // after it.
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000491 const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000492 if (getLexer().isNot(AsmToken::LParen)) {
Chris Lattnere17df0b2010-01-15 19:39:23 +0000493 SMLoc ExprEnd;
494 if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000495
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000496 // After parsing the base expression we could either have a parenthesized
497 // memory address or not. If not, return now. If so, eat the (.
498 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000499 // Unless we have a segment register, treat this as an immediate.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000500 if (SegReg == 0)
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000501 return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
Chris Lattner015cfb12010-01-15 19:33:43 +0000502 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000503 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000504
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000505 // Eat the '('.
Sean Callanana83fd7d2010-01-19 20:27:46 +0000506 Parser.Lex();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000507 } else {
508 // Okay, we have a '('. We don't know if this is an expression or not, but
509 // so we have to eat the ( to see beyond it.
Sean Callanan936b0d32010-01-19 21:44:56 +0000510 SMLoc LParenLoc = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000511 Parser.Lex(); // Eat the '('.
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000512
Kevin Enderby7d912182009-09-03 17:15:07 +0000513 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000514 // Nothing to do here, fall into the code below with the '(' part of the
515 // memory operand consumed.
516 } else {
Chris Lattner528d00b2010-01-15 19:28:38 +0000517 SMLoc ExprEnd;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000518
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000519 // It must be an parenthesized expression, parse it now.
Chris Lattner528d00b2010-01-15 19:28:38 +0000520 if (getParser().ParseParenExpression(Disp, ExprEnd))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000521 return 0;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000522
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000523 // After parsing the base expression we could either have a parenthesized
524 // memory address or not. If not, return now. If so, eat the (.
525 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000526 // Unless we have a segment register, treat this as an immediate.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000527 if (SegReg == 0)
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000528 return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
Chris Lattner015cfb12010-01-15 19:33:43 +0000529 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000530 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000531
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000532 // Eat the '('.
Sean Callanana83fd7d2010-01-19 20:27:46 +0000533 Parser.Lex();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000534 }
535 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000536
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000537 // If we reached here, then we just ate the ( of the memory operand. Process
538 // the rest of the memory operand.
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000539 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000540
Chris Lattner0c2538f2010-01-15 18:51:29 +0000541 if (getLexer().is(AsmToken::Percent)) {
542 SMLoc L;
543 if (ParseRegister(BaseReg, L, L)) return 0;
Bruno Cardoso Lopes306a1f92010-07-24 00:06:39 +0000544 if (BaseReg == X86::EIZ || BaseReg == X86::RIZ) {
545 Error(L, "eiz and riz can only be used as index registers");
546 return 0;
547 }
Chris Lattner0c2538f2010-01-15 18:51:29 +0000548 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000549
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000550 if (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +0000551 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000552
553 // Following the comma we should have either an index register, or a scale
554 // value. We don't support the later form, but we want to parse it
555 // correctly.
556 //
557 // Not that even though it would be completely consistent to support syntax
Bruno Cardoso Lopes306a1f92010-07-24 00:06:39 +0000558 // like "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
Kevin Enderby7d912182009-09-03 17:15:07 +0000559 if (getLexer().is(AsmToken::Percent)) {
Chris Lattner0c2538f2010-01-15 18:51:29 +0000560 SMLoc L;
561 if (ParseRegister(IndexReg, L, L)) return 0;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000562
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000563 if (getLexer().isNot(AsmToken::RParen)) {
564 // Parse the scale amount:
565 // ::= ',' [scale-expression]
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000566 if (getLexer().isNot(AsmToken::Comma)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000567 Error(Parser.getTok().getLoc(),
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000568 "expected comma in scale expression");
569 return 0;
570 }
Sean Callanana83fd7d2010-01-19 20:27:46 +0000571 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000572
573 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000574 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000575
576 int64_t ScaleVal;
577 if (getParser().ParseAbsoluteExpression(ScaleVal))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000578 return 0;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000579
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000580 // Validate the scale amount.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000581 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
582 Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
583 return 0;
584 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000585 Scale = (unsigned)ScaleVal;
586 }
587 }
588 } else if (getLexer().isNot(AsmToken::RParen)) {
Daniel Dunbar94b84a12010-08-24 19:13:38 +0000589 // A scale amount without an index is ignored.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000590 // index.
Sean Callanan936b0d32010-01-19 21:44:56 +0000591 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000592
593 int64_t Value;
594 if (getParser().ParseAbsoluteExpression(Value))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000595 return 0;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000596
Daniel Dunbar94b84a12010-08-24 19:13:38 +0000597 if (Value != 1)
598 Warning(Loc, "scale factor without index register is ignored");
599 Scale = 1;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000600 }
601 }
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000602
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000603 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000604 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000605 Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000606 return 0;
607 }
Sean Callanan936b0d32010-01-19 21:44:56 +0000608 SMLoc MemEnd = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000609 Parser.Lex(); // Eat the ')'.
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000610
Chris Lattner015cfb12010-01-15 19:33:43 +0000611 return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
612 MemStart, MemEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000613}
614
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000615bool X86ATTAsmParser::
Benjamin Kramer92d89982010-07-14 22:38:02 +0000616ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000617 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000618 // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
619 // represent alternative syntaxes in the .td file, without requiring
620 // instruction duplication.
621 StringRef PatchedName = StringSwitch<StringRef>(Name)
622 .Case("sal", "shl")
623 .Case("salb", "shlb")
624 .Case("sall", "shll")
625 .Case("salq", "shlq")
626 .Case("salw", "shlw")
627 .Case("repe", "rep")
628 .Case("repz", "rep")
629 .Case("repnz", "repne")
Chris Lattner063363f2010-09-08 05:38:31 +0000630 .Case("iret", "iretl")
Chris Lattnera9ca7832010-09-08 05:45:34 +0000631 .Case("sysret", "sysretl")
Chris Lattner415e04f2010-09-06 23:40:56 +0000632 .Case("push", Is64Bit ? "pushq" : "pushl")
Chris Lattner8ead2372010-09-08 22:13:08 +0000633 .Case("pop", Is64Bit ? "popq" : "popl")
Dan Gohman29790ed2010-05-20 16:16:00 +0000634 .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
635 .Case("popf", Is64Bit ? "popfq" : "popfl")
Chris Lattnerb47c0422010-09-11 16:39:16 +0000636 .Case("pushfd", "pushfl")
637 .Case("popfd", "popfl")
Kevin Enderby7e7482c2010-05-21 23:01:38 +0000638 .Case("retl", Is64Bit ? "retl" : "ret")
639 .Case("retq", Is64Bit ? "ret" : "retq")
Chris Lattner3340c3e2010-09-11 17:06:05 +0000640 .Case("setz", "sete") .Case("setnz", "setne")
641 .Case("setc", "setb") .Case("setna", "setbe")
642 .Case("setnae", "setb").Case("setnb", "setae")
643 .Case("setnbe", "seta").Case("setnc", "setae")
644 .Case("setng", "setle").Case("setnge", "setl")
645 .Case("setnl", "setge").Case("setnle", "setg")
646 .Case("setpe", "setp") .Case("setpo", "setnp")
647 .Case("jz", "je") .Case("jnz", "jne")
648 .Case("jc", "jb") .Case("jna", "jbe")
649 .Case("jnae", "jb").Case("jnb", "jae")
650 .Case("jnbe", "ja").Case("jnc", "jae")
651 .Case("jng", "jle").Case("jnge", "jl")
652 .Case("jnl", "jge").Case("jnle", "jg")
653 .Case("jpe", "jp") .Case("jpo", "jnp")
Chris Lattner30bb3842010-09-07 00:05:45 +0000654 // Condition code aliases for 16-bit, 32-bit, 64-bit and unspec operands.
655 .Case("cmovcw", "cmovbw") .Case("cmovcl", "cmovbl")
656 .Case("cmovcq", "cmovbq") .Case("cmovc", "cmovb")
Chris Lattner1bbb14a2010-09-11 17:08:22 +0000657 .Case("cmovnaew","cmovbw") .Case("cmovnael","cmovbl")
658 .Case("cmovnaeq","cmovbq") .Case("cmovnae", "cmovb")
Chris Lattner30bb3842010-09-07 00:05:45 +0000659 .Case("cmovnaw", "cmovbew").Case("cmovnal", "cmovbel")
660 .Case("cmovnaq", "cmovbeq").Case("cmovna", "cmovbe")
661 .Case("cmovnbw", "cmovaew").Case("cmovnbl", "cmovael")
662 .Case("cmovnbq", "cmovaeq").Case("cmovnb", "cmovae")
663 .Case("cmovnbew","cmovaw") .Case("cmovnbel","cmoval")
664 .Case("cmovnbeq","cmovaq") .Case("cmovnbe", "cmova")
665 .Case("cmovncw", "cmovaew").Case("cmovncl", "cmovael")
666 .Case("cmovncq", "cmovaeq").Case("cmovnc", "cmovae")
667 .Case("cmovngw", "cmovlew").Case("cmovngl", "cmovlel")
668 .Case("cmovngq", "cmovleq").Case("cmovng", "cmovle")
669 .Case("cmovnw", "cmovgew").Case("cmovnl", "cmovgel")
670 .Case("cmovnq", "cmovgeq").Case("cmovn", "cmovge")
671 .Case("cmovngw", "cmovlew").Case("cmovngl", "cmovlel")
672 .Case("cmovngq", "cmovleq").Case("cmovng", "cmovle")
673 .Case("cmovngew","cmovlw") .Case("cmovngel","cmovll")
674 .Case("cmovngeq","cmovlq") .Case("cmovnge", "cmovl")
675 .Case("cmovnlw", "cmovgew").Case("cmovnll", "cmovgel")
676 .Case("cmovnlq", "cmovgeq").Case("cmovnl", "cmovge")
677 .Case("cmovnlew","cmovgw") .Case("cmovnlel","cmovgl")
678 .Case("cmovnleq","cmovgq") .Case("cmovnle", "cmovg")
679 .Case("cmovnzw", "cmovnew").Case("cmovnzl", "cmovnel")
680 .Case("cmovnzq", "cmovneq").Case("cmovnz", "cmovne")
681 .Case("cmovzw", "cmovew") .Case("cmovzl", "cmovel")
682 .Case("cmovzq", "cmoveq") .Case("cmovz", "cmove")
Kevin Enderbyb2922892010-05-28 20:59:10 +0000683 .Case("fwait", "wait")
Kevin Enderby4c71e082010-05-28 21:20:21 +0000684 .Case("movzx", "movzb")
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000685 .Default(Name);
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000686
687 // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
688 const MCExpr *ExtraImmOp = 0;
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000689 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000690 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
691 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000692 bool IsVCMP = PatchedName.startswith("vcmp");
693 unsigned SSECCIdx = IsVCMP ? 4 : 3;
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000694 unsigned SSEComparisonCode = StringSwitch<unsigned>(
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000695 PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
Bruno Cardoso Lopes6c614512010-07-07 22:24:03 +0000696 .Case("eq", 0)
697 .Case("lt", 1)
698 .Case("le", 2)
699 .Case("unord", 3)
700 .Case("neq", 4)
701 .Case("nlt", 5)
702 .Case("nle", 6)
703 .Case("ord", 7)
704 .Case("eq_uq", 8)
705 .Case("nge", 9)
706 .Case("ngt", 0x0A)
707 .Case("false", 0x0B)
708 .Case("neq_oq", 0x0C)
709 .Case("ge", 0x0D)
710 .Case("gt", 0x0E)
711 .Case("true", 0x0F)
712 .Case("eq_os", 0x10)
713 .Case("lt_oq", 0x11)
714 .Case("le_oq", 0x12)
715 .Case("unord_s", 0x13)
716 .Case("neq_us", 0x14)
717 .Case("nlt_uq", 0x15)
718 .Case("nle_uq", 0x16)
719 .Case("ord_s", 0x17)
720 .Case("eq_us", 0x18)
721 .Case("nge_uq", 0x19)
722 .Case("ngt_uq", 0x1A)
723 .Case("false_os", 0x1B)
724 .Case("neq_os", 0x1C)
725 .Case("ge_oq", 0x1D)
726 .Case("gt_oq", 0x1E)
727 .Case("true_us", 0x1F)
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000728 .Default(~0U);
729 if (SSEComparisonCode != ~0U) {
730 ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode,
731 getParser().getContext());
732 if (PatchedName.endswith("ss")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000733 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000734 } else if (PatchedName.endswith("sd")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000735 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000736 } else if (PatchedName.endswith("ps")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000737 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000738 } else {
739 assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000740 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000741 }
742 }
743 }
Bruno Cardoso Lopesea0e05a2010-07-23 18:41:12 +0000744
745 // FIXME: Hack to recognize vpclmul<src1_quadword, src2_quadword>dq
746 if (PatchedName.startswith("vpclmul")) {
747 unsigned CLMULQuadWordSelect = StringSwitch<unsigned>(
748 PatchedName.slice(7, PatchedName.size() - 2))
749 .Case("lqlq", 0x00) // src1[63:0], src2[63:0]
750 .Case("hqlq", 0x01) // src1[127:64], src2[63:0]
751 .Case("lqhq", 0x10) // src1[63:0], src2[127:64]
752 .Case("hqhq", 0x11) // src1[127:64], src2[127:64]
753 .Default(~0U);
754 if (CLMULQuadWordSelect != ~0U) {
755 ExtraImmOp = MCConstantExpr::Create(CLMULQuadWordSelect,
756 getParser().getContext());
757 assert(PatchedName.endswith("dq") && "Unexpected mnemonic!");
758 PatchedName = "vpclmulqdq";
759 }
760 }
Chris Lattner8caea682010-09-08 04:53:27 +0000761
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000762 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000763
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000764 if (ExtraImmOp)
765 Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
Chris Lattner4cfbcdc2010-09-06 18:32:06 +0000766
Chris Lattner086a83a2010-09-08 05:17:37 +0000767
768 // Determine whether this is an instruction prefix.
769 bool isPrefix =
770 PatchedName == "lock" || PatchedName == "rep" ||
771 PatchedName == "repne";
772
773
774 // This does the actual operand parsing. Don't parse any more if we have a
775 // prefix juxtaposed with an operation like "lock incl 4(%rax)", because we
776 // just want to parse the "lock" as the first instruction and the "incl" as
777 // the next one.
778 if (getLexer().isNot(AsmToken::EndOfStatement) && !isPrefix) {
Daniel Dunbar71527c12009-08-11 05:00:25 +0000779
780 // Parse '*' modifier.
781 if (getLexer().is(AsmToken::Star)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000782 SMLoc Loc = Parser.getTok().getLoc();
Chris Lattner528d00b2010-01-15 19:28:38 +0000783 Operands.push_back(X86Operand::CreateToken("*", Loc));
Sean Callanana83fd7d2010-01-19 20:27:46 +0000784 Parser.Lex(); // Eat the star.
Daniel Dunbar71527c12009-08-11 05:00:25 +0000785 }
786
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000787 // Read the first operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000788 if (X86Operand *Op = ParseOperand())
789 Operands.push_back(Op);
Chris Lattnera2a9d162010-09-11 16:18:25 +0000790 else {
791 Parser.EatToEndOfStatement();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000792 return true;
Chris Lattnera2a9d162010-09-11 16:18:25 +0000793 }
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000794
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000795 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +0000796 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000797
798 // Parse and remember the operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000799 if (X86Operand *Op = ParseOperand())
800 Operands.push_back(Op);
Chris Lattnera2a9d162010-09-11 16:18:25 +0000801 else {
802 Parser.EatToEndOfStatement();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000803 return true;
Chris Lattnera2a9d162010-09-11 16:18:25 +0000804 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000805 }
Chris Lattner086a83a2010-09-08 05:17:37 +0000806
Chris Lattnera2a9d162010-09-11 16:18:25 +0000807 if (getLexer().isNot(AsmToken::EndOfStatement)) {
808 Parser.EatToEndOfStatement();
Chris Lattner086a83a2010-09-08 05:17:37 +0000809 return TokError("unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +0000810 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000811 }
Chris Lattner91689c12010-09-08 05:10:46 +0000812
Chris Lattner086a83a2010-09-08 05:17:37 +0000813 if (getLexer().is(AsmToken::EndOfStatement))
814 Parser.Lex(); // Consume the EndOfStatement
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000815
Chris Lattner30561ab2010-09-11 16:32:12 +0000816 // FIXME: Hack to handle recognize s{hr,ar,hl} <op>, $1. Canonicalize to
817 // "shift <op>".
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000818 if ((Name.startswith("shr") || Name.startswith("sar") ||
819 Name.startswith("shl")) &&
Chris Lattner4cfbcdc2010-09-06 18:32:06 +0000820 Operands.size() == 3) {
821 X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]);
822 if (Op1->isImm() && isa<MCConstantExpr>(Op1->getImm()) &&
823 cast<MCConstantExpr>(Op1->getImm())->getValue() == 1) {
824 delete Operands[1];
825 Operands.erase(Operands.begin() + 1);
826 }
Daniel Dunbarfbd12cc2010-03-20 22:36:38 +0000827 }
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000828
Chris Lattner30561ab2010-09-11 16:32:12 +0000829 // FIXME: Hack to handle recognize "in[bwl] <op>". Canonicalize it to
830 // "inb <op>, %al".
831 if ((Name == "inb" || Name == "inw" || Name == "inl") &&
832 Operands.size() == 2) {
833 unsigned Reg;
834 if (Name[2] == 'b')
835 Reg = MatchRegisterName("al");
836 else if (Name[2] == 'w')
837 Reg = MatchRegisterName("ax");
838 else
839 Reg = MatchRegisterName("eax");
840 SMLoc Loc = Operands.back()->getEndLoc();
841 Operands.push_back(X86Operand::CreateReg(Reg, Loc, Loc));
842 }
843
844 // FIXME: Hack to handle recognize "out[bwl] <op>". Canonicalize it to
845 // "outb %al, <op>".
846 if ((Name == "outb" || Name == "outw" || Name == "outl") &&
847 Operands.size() == 2) {
848 unsigned Reg;
849 if (Name[3] == 'b')
850 Reg = MatchRegisterName("al");
851 else if (Name[3] == 'w')
852 Reg = MatchRegisterName("ax");
853 else
854 Reg = MatchRegisterName("eax");
855 SMLoc Loc = Operands.back()->getEndLoc();
856 Operands.push_back(X86Operand::CreateReg(Reg, Loc, Loc));
857 std::swap(Operands[1], Operands[2]);
858 }
859
Chris Lattner5f2311d2010-09-14 23:34:29 +0000860 // FIXME: Hack to handle "out[bwl]? %al, (%dx)" -> "outb %al, %dx".
861 if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") &&
862 Operands.size() == 3) {
863 X86Operand &Op = *(X86Operand*)Operands.back();
864 if (Op.isMem() && Op.Mem.SegReg == 0 &&
865 isa<MCConstantExpr>(Op.Mem.Disp) &&
866 cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 &&
867 Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
868 SMLoc Loc = Op.getEndLoc();
869 Operands.back() = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
870 delete &Op;
871 }
872 }
873
Kevin Enderby492d4f42010-05-25 20:52:34 +0000874 // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
875 // "f{mul*,add*,sub*,div*} $op"
876 if ((Name.startswith("fmul") || Name.startswith("fadd") ||
877 Name.startswith("fsub") || Name.startswith("fdiv")) &&
878 Operands.size() == 3 &&
879 static_cast<X86Operand*>(Operands[2])->isReg() &&
880 static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
881 delete Operands[2];
882 Operands.erase(Operands.begin() + 2);
883 }
884
Daniel Dunbar1c8d7772010-08-24 19:37:56 +0000885 // FIXME: Hack to handle "imul <imm>, B" which is an alias for "imul <imm>, B,
886 // B".
Daniel Dunbar09392782010-08-24 19:24:18 +0000887 if (Name.startswith("imul") && Operands.size() == 3 &&
Daniel Dunbar1c8d7772010-08-24 19:37:56 +0000888 static_cast<X86Operand*>(Operands[1])->isImm() &&
Daniel Dunbar09392782010-08-24 19:24:18 +0000889 static_cast<X86Operand*>(Operands.back())->isReg()) {
890 X86Operand *Op = static_cast<X86Operand*>(Operands.back());
891 Operands.push_back(X86Operand::CreateReg(Op->getReg(), Op->getStartLoc(),
892 Op->getEndLoc()));
893 }
Chris Lattner7ece7162010-09-06 23:51:44 +0000894
895 // 'sldt <mem>' can be encoded with either sldtw or sldtq with the same
896 // effect (both store to a 16-bit mem). Force to sldtw to avoid ambiguity
897 // errors, since its encoding is the most compact.
898 if (Name == "sldt" && Operands.size() == 2 &&
Benjamin Kramer1ecb9782010-09-07 14:40:58 +0000899 static_cast<X86Operand*>(Operands[1])->isMem()) {
900 delete Operands[0];
Chris Lattner7ece7162010-09-06 23:51:44 +0000901 Operands[0] = X86Operand::CreateToken("sldtw", NameLoc);
Benjamin Kramer1ecb9782010-09-07 14:40:58 +0000902 }
Chris Lattner8caea682010-09-08 04:53:27 +0000903
904 // The assembler accepts "xchgX <reg>, <mem>" and "xchgX <mem>, <reg>" as
905 // synonyms. Our tables only have the "<reg>, <mem>" form, so if we see the
906 // other operand order, swap them.
Chris Lattner28a9c2f2010-09-08 22:27:05 +0000907 if (Name == "xchgb" || Name == "xchgw" || Name == "xchgl" || Name == "xchgq"||
908 Name == "xchg")
Chris Lattner8caea682010-09-08 04:53:27 +0000909 if (Operands.size() == 3 &&
910 static_cast<X86Operand*>(Operands[1])->isMem() &&
911 static_cast<X86Operand*>(Operands[2])->isReg()) {
912 std::swap(Operands[1], Operands[2]);
913 }
Daniel Dunbar09392782010-08-24 19:24:18 +0000914
Chris Lattner2907d2e2010-09-08 05:51:12 +0000915 // The assembler accepts "testX <reg>, <mem>" and "testX <mem>, <reg>" as
916 // synonyms. Our tables only have the "<mem>, <reg>" form, so if we see the
917 // other operand order, swap them.
Chris Lattner28a9c2f2010-09-08 22:27:05 +0000918 if (Name == "testb" || Name == "testw" || Name == "testl" || Name == "testq"||
919 Name == "test")
Chris Lattner2907d2e2010-09-08 05:51:12 +0000920 if (Operands.size() == 3 &&
921 static_cast<X86Operand*>(Operands[1])->isReg() &&
922 static_cast<X86Operand*>(Operands[2])->isMem()) {
923 std::swap(Operands[1], Operands[2]);
924 }
925
Chris Lattner4dbcba02010-09-15 04:04:33 +0000926 // The assembler accepts these instructions with no operand as a synonym for
927 // an instruction acting on st(1). e.g. "fxch" -> "fxch %st(1)".
928 if ((Name == "fxch" || Name == "fucom" || Name == "fucomp" ||
929 Name == "faddp" || Name == "fsubp" || Name == "fsubrp" ||
930 Name == "fmulp" || Name == "fdivp" || Name == "fdivrp") &&
931 Operands.size() == 1) {
932 Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(1)"),
933 NameLoc, NameLoc));
934 }
935
Chris Lattner7df35db2010-09-15 04:08:38 +0000936 // The assembler accepts these instructions with two few operands as a synonym
937 // for taking %st(1),%st(0) or X, %st(0).
938 if ((Name == "fcomi" || Name == "fucomi") && Operands.size() < 3) {
939 if (Operands.size() == 1)
940 Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(1)"),
941 NameLoc, NameLoc));
942 Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(0)"),
943 NameLoc, NameLoc));
944 }
Chris Lattner4dbcba02010-09-15 04:04:33 +0000945
Chris Lattner81ce1732010-09-15 04:15:16 +0000946 // The assembler accepts various amounts of brokenness for fnstsw.
947 if (Name == "fnstsw") {
948 if (Operands.size() == 2 &&
949 static_cast<X86Operand*>(Operands[1])->isReg()) {
950 // "fnstsw al" and "fnstsw eax" -> "fnstw"
951 unsigned Reg = static_cast<X86Operand*>(Operands[1])->Reg.RegNo;
952 if (Reg == MatchRegisterName("eax") ||
953 Reg == MatchRegisterName("al")) {
954 delete Operands[1];
955 Operands.pop_back();
956 }
957 }
958
959 // "fnstw" -> "fnstw %ax"
960 if (Operands.size() == 1)
961 Operands.push_back(X86Operand::CreateReg(MatchRegisterName("ax"),
962 NameLoc, NameLoc));
963 }
964
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000965 return false;
Daniel Dunbar3c2a8932009-07-20 18:55:04 +0000966}
967
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000968bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
969 StringRef IDVal = DirectiveID.getIdentifier();
970 if (IDVal == ".word")
971 return ParseDirectiveWord(2, DirectiveID.getLoc());
972 return true;
973}
974
975/// ParseDirectiveWord
976/// ::= .word [ expression (, expression)* ]
977bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
978 if (getLexer().isNot(AsmToken::EndOfStatement)) {
979 for (;;) {
980 const MCExpr *Value;
981 if (getParser().ParseExpression(Value))
982 return true;
983
Chris Lattnerc35681b2010-01-19 19:46:13 +0000984 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000985
986 if (getLexer().is(AsmToken::EndOfStatement))
987 break;
Bruno Cardoso Lopesd65cd1d2010-07-23 22:15:26 +0000988
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000989 // FIXME: Improve diagnostic.
990 if (getLexer().isNot(AsmToken::Comma))
991 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +0000992 Parser.Lex();
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000993 }
994 }
995
Sean Callanana83fd7d2010-01-19 20:27:46 +0000996 Parser.Lex();
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000997 return false;
998}
999
Daniel Dunbar2ecc3bb2010-08-12 00:55:38 +00001000
Chris Lattner4dbcba02010-09-15 04:04:33 +00001001bool X86ATTAsmParser::
1002MatchInstruction(SMLoc IDLoc,
1003 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1004 MCInst &Inst) {
Daniel Dunbar2ecc3bb2010-08-12 00:55:38 +00001005 assert(!Operands.empty() && "Unexpect empty operand list!");
1006
Chris Lattner628fbec2010-09-06 21:54:15 +00001007 bool WasOriginallyInvalidOperand = false;
Chris Lattner339cc7b2010-09-06 22:11:18 +00001008 unsigned OrigErrorInfo;
Chris Lattner628fbec2010-09-06 21:54:15 +00001009
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001010 // First, try a direct match.
Chris Lattner339cc7b2010-09-06 22:11:18 +00001011 switch (MatchInstructionImpl(Operands, Inst, OrigErrorInfo)) {
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001012 case Match_Success:
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001013 return false;
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001014 case Match_MissingFeature:
1015 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1016 return true;
Chris Lattner628fbec2010-09-06 21:54:15 +00001017 case Match_InvalidOperand:
1018 WasOriginallyInvalidOperand = true;
1019 break;
1020 case Match_MnemonicFail:
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001021 break;
1022 }
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001023
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001024 // FIXME: Ideally, we would only attempt suffix matches for things which are
1025 // valid prefixes, and we could just infer the right unambiguous
1026 // type. However, that requires substantially more matcher support than the
1027 // following hack.
1028
Chris Lattner3e4582a2010-09-06 19:11:01 +00001029 X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
1030 assert(Op->isToken() && "Leading operand should always be a mnemonic!");
1031
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001032 // Change the operand to point to a temporary token.
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001033 StringRef Base = Op->getToken();
Daniel Dunbar2ecc3bb2010-08-12 00:55:38 +00001034 SmallString<16> Tmp;
1035 Tmp += Base;
1036 Tmp += ' ';
1037 Op->setTokenValue(Tmp.str());
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001038
1039 // Check for the various suffix matches.
1040 Tmp[Base.size()] = 'b';
Chris Lattner339cc7b2010-09-06 22:11:18 +00001041 unsigned BErrorInfo, WErrorInfo, LErrorInfo, QErrorInfo;
1042 MatchResultTy MatchB = MatchInstructionImpl(Operands, Inst, BErrorInfo);
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001043 Tmp[Base.size()] = 'w';
Chris Lattner339cc7b2010-09-06 22:11:18 +00001044 MatchResultTy MatchW = MatchInstructionImpl(Operands, Inst, WErrorInfo);
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001045 Tmp[Base.size()] = 'l';
Chris Lattner339cc7b2010-09-06 22:11:18 +00001046 MatchResultTy MatchL = MatchInstructionImpl(Operands, Inst, LErrorInfo);
Daniel Dunbar059379a2010-05-12 00:54:20 +00001047 Tmp[Base.size()] = 'q';
Chris Lattner339cc7b2010-09-06 22:11:18 +00001048 MatchResultTy MatchQ = MatchInstructionImpl(Operands, Inst, QErrorInfo);
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001049
1050 // Restore the old token.
1051 Op->setTokenValue(Base);
1052
1053 // If exactly one matched, then we treat that as a successful match (and the
1054 // instruction will already have been filled in correctly, since the failing
1055 // matches won't have modified it).
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001056 unsigned NumSuccessfulMatches =
1057 (MatchB == Match_Success) + (MatchW == Match_Success) +
1058 (MatchL == Match_Success) + (MatchQ == Match_Success);
1059 if (NumSuccessfulMatches == 1)
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001060 return false;
1061
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001062 // Otherwise, the match failed, try to produce a decent error message.
Daniel Dunbar2ecc3bb2010-08-12 00:55:38 +00001063
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001064 // If we had multiple suffix matches, then identify this as an ambiguous
1065 // match.
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001066 if (NumSuccessfulMatches > 1) {
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001067 char MatchChars[4];
1068 unsigned NumMatches = 0;
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001069 if (MatchB == Match_Success)
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001070 MatchChars[NumMatches++] = 'b';
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001071 if (MatchW == Match_Success)
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001072 MatchChars[NumMatches++] = 'w';
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001073 if (MatchL == Match_Success)
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001074 MatchChars[NumMatches++] = 'l';
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001075 if (MatchQ == Match_Success)
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001076 MatchChars[NumMatches++] = 'q';
1077
1078 SmallString<126> Msg;
1079 raw_svector_ostream OS(Msg);
1080 OS << "ambiguous instructions require an explicit suffix (could be ";
1081 for (unsigned i = 0; i != NumMatches; ++i) {
1082 if (i != 0)
1083 OS << ", ";
1084 if (i + 1 == NumMatches)
1085 OS << "or ";
1086 OS << "'" << Base << MatchChars[i] << "'";
1087 }
1088 OS << ")";
1089 Error(IDLoc, OS.str());
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001090 return true;
Daniel Dunbar7d7b4d12010-08-12 00:55:42 +00001091 }
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001092
Chris Lattner628fbec2010-09-06 21:54:15 +00001093 // Okay, we know that none of the variants matched successfully.
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001094
Chris Lattner628fbec2010-09-06 21:54:15 +00001095 // If all of the instructions reported an invalid mnemonic, then the original
1096 // mnemonic was invalid.
1097 if ((MatchB == Match_MnemonicFail) && (MatchW == Match_MnemonicFail) &&
1098 (MatchL == Match_MnemonicFail) && (MatchQ == Match_MnemonicFail)) {
Chris Lattner339cc7b2010-09-06 22:11:18 +00001099 if (!WasOriginallyInvalidOperand) {
Chris Lattner628fbec2010-09-06 21:54:15 +00001100 Error(IDLoc, "invalid instruction mnemonic '" + Base + "'");
Chris Lattner339cc7b2010-09-06 22:11:18 +00001101 return true;
1102 }
1103
1104 // Recover location info for the operand if we know which was the problem.
1105 SMLoc ErrorLoc = IDLoc;
1106 if (OrigErrorInfo != ~0U) {
Chris Lattnerd28452d2010-09-15 03:50:11 +00001107 if (OrigErrorInfo >= Operands.size())
1108 return Error(IDLoc, "too few operands for instruction");
1109
Chris Lattner339cc7b2010-09-06 22:11:18 +00001110 ErrorLoc = ((X86Operand*)Operands[OrigErrorInfo])->getStartLoc();
1111 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
1112 }
1113
Chris Lattnerd28452d2010-09-15 03:50:11 +00001114 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner628fbec2010-09-06 21:54:15 +00001115 }
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001116
1117 // If one instruction matched with a missing feature, report this as a
1118 // missing feature.
1119 if ((MatchB == Match_MissingFeature) + (MatchW == Match_MissingFeature) +
Chris Lattner628fbec2010-09-06 21:54:15 +00001120 (MatchL == Match_MissingFeature) + (MatchQ == Match_MissingFeature) == 1){
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001121 Error(IDLoc, "instruction requires a CPU feature not currently enabled");
1122 return true;
1123 }
1124
Chris Lattner628fbec2010-09-06 21:54:15 +00001125 // If one instruction matched with an invalid operand, report this as an
1126 // operand failure.
1127 if ((MatchB == Match_InvalidOperand) + (MatchW == Match_InvalidOperand) +
1128 (MatchL == Match_InvalidOperand) + (MatchQ == Match_InvalidOperand) == 1){
1129 Error(IDLoc, "invalid operand for instruction");
1130 return true;
1131 }
1132
Chris Lattnerb4be28f2010-09-06 20:08:02 +00001133 // If all of these were an outright failure, report it in a useless way.
1134 // FIXME: We should give nicer diagnostics about the exact failure.
Chris Lattner628fbec2010-09-06 21:54:15 +00001135 Error(IDLoc, "unknown use of instruction mnemonic without a size suffix");
Daniel Dunbar9b816a12010-05-04 16:12:42 +00001136 return true;
1137}
1138
1139
Sean Callanan5051cb82010-01-23 02:43:15 +00001140extern "C" void LLVMInitializeX86AsmLexer();
1141
Daniel Dunbar71475772009-07-17 20:42:00 +00001142// Force static initialization.
1143extern "C" void LLVMInitializeX86AsmParser() {
Daniel Dunbar63ec0932010-03-18 20:06:02 +00001144 RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
1145 RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
Sean Callanan5051cb82010-01-23 02:43:15 +00001146 LLVMInitializeX86AsmLexer();
Daniel Dunbar71475772009-07-17 20:42:00 +00001147}
Daniel Dunbar00331992009-07-29 00:02:19 +00001148
Chris Lattner3e4582a2010-09-06 19:11:01 +00001149#define GET_REGISTER_MATCHER
1150#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar00331992009-07-29 00:02:19 +00001151#include "X86GenAsmMatcher.inc"