blob: 874a38ad0ed9964b4be47752a961a5763d081633 [file] [log] [blame]
Daniel Dunbar092a9dd2009-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 Lattner98986712010-01-14 22:21:20 +000010#include "llvm/Target/TargetAsmParser.h"
Daniel Dunbar4cb1e132009-07-18 23:03:22 +000011#include "X86.h"
Daniel Dunbar54074b52010-07-19 05:44:09 +000012#include "X86Subtarget.h"
Daniel Dunbardbd692a2009-07-20 20:01:54 +000013#include "llvm/ADT/SmallVector.h"
Daniel Dunbar1b6c0602010-02-10 21:19:28 +000014#include "llvm/ADT/StringSwitch.h"
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000015#include "llvm/ADT/Twine.h"
Kevin Enderby9c656452009-09-10 20:51:44 +000016#include "llvm/MC/MCStreamer.h"
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +000017#include "llvm/MC/MCExpr.h"
Daniel Dunbara027d222009-07-31 02:32:59 +000018#include "llvm/MC/MCInst.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
20#include "llvm/MC/MCParser/MCAsmParser.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000022#include "llvm/Support/SourceMgr.h"
Daniel Dunbar092a9dd2009-07-17 20:42:00 +000023#include "llvm/Target/TargetRegistry.h"
24#include "llvm/Target/TargetAsmParser.h"
25using namespace llvm;
26
27namespace {
Benjamin Kramerc6b79ac2009-07-31 11:35:26 +000028struct X86Operand;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000029
30class X86ATTAsmParser : public TargetAsmParser {
31 MCAsmParser &Parser;
Daniel Dunbard73ada72010-07-19 00:33:49 +000032 TargetMachine &TM;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000033
Daniel Dunbarf98bc632010-03-18 20:06:02 +000034protected:
35 unsigned Is64Bit : 1;
36
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000037private:
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000038 MCAsmParser &getParser() const { return Parser; }
39
40 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
41
42 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
43
44 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
45
Chris Lattner29ef9a22010-01-15 18:51:29 +000046 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000047
Chris Lattner309264d2010-01-15 18:44:13 +000048 X86Operand *ParseOperand();
Chris Lattnereef6d782010-04-17 18:56:34 +000049 X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
Kevin Enderby9c656452009-09-10 20:51:44 +000050
51 bool ParseDirectiveWord(unsigned Size, SMLoc L);
52
Chris Lattner98986712010-01-14 22:21:20 +000053 bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbar20927f22009-08-07 08:26:05 +000054 MCInst &Inst);
55
Daniel Dunbar54074b52010-07-19 05:44:09 +000056 /// @name Auto-generated Matcher Functions
57 /// {
58
59 unsigned ComputeAvailableFeatures(const X86Subtarget *Subtarget) const;
60
Daniel Dunbarc918d602010-05-04 16:12:42 +000061 bool MatchInstructionImpl(
62 const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst);
63
Daniel Dunbar0e2771f2009-07-29 00:02:19 +000064 /// }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000065
66public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000067 X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
Daniel Dunbar54074b52010-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 Dunbar16cdcb32009-07-28 22:40:46 +000074
Benjamin Kramer38e59892010-07-14 22:38:02 +000075 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +000076 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderby9c656452009-09-10 20:51:44 +000077
78 virtual bool ParseDirective(AsmToken DirectiveID);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000079};
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +000080
Daniel Dunbarf98bc632010-03-18 20:06:02 +000081class X86_32ATTAsmParser : public X86ATTAsmParser {
82public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000083 X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
84 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbarf98bc632010-03-18 20:06:02 +000085 Is64Bit = false;
86 }
87};
88
89class X86_64ATTAsmParser : public X86ATTAsmParser {
90public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000091 X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
92 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbarf98bc632010-03-18 20:06:02 +000093 Is64Bit = true;
94 }
95};
96
Chris Lattner37dfdec2009-07-29 06:33:53 +000097} // end anonymous namespace
98
Sean Callanane9b466d2010-01-23 00:40:33 +000099/// @name Auto-generated Match Functions
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000100/// {
Sean Callanane9b466d2010-01-23 00:40:33 +0000101
Chris Lattnerb8d6e982010-02-09 00:34:28 +0000102static unsigned MatchRegisterName(StringRef Name);
Sean Callanane9b466d2010-01-23 00:40:33 +0000103
104/// }
Chris Lattner37dfdec2009-07-29 06:33:53 +0000105
106namespace {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000107
108/// X86Operand - Instances of this class represent a parsed X86 machine
109/// instruction.
Chris Lattner45220a82010-01-14 21:20:55 +0000110struct X86Operand : public MCParsedAsmOperand {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000111 enum KindTy {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000112 Token,
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000113 Register,
114 Immediate,
115 Memory
116 } Kind;
117
Chris Lattner29ef9a22010-01-15 18:51:29 +0000118 SMLoc StartLoc, EndLoc;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000119
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000120 union {
121 struct {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000122 const char *Data;
123 unsigned Length;
124 } Tok;
125
126 struct {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000127 unsigned RegNo;
128 } Reg;
129
130 struct {
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000131 const MCExpr *Val;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000132 } Imm;
133
134 struct {
135 unsigned SegReg;
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000136 const MCExpr *Disp;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000137 unsigned BaseReg;
138 unsigned IndexReg;
139 unsigned Scale;
140 } Mem;
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000141 };
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000142
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000143 X86Operand(KindTy K, SMLoc Start, SMLoc End)
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000144 : Kind(K), StartLoc(Start), EndLoc(End) {}
Daniel Dunbarc918d602010-05-04 16:12:42 +0000145
Chris Lattner1f19f0f2010-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 Dunbarb3cb6962010-08-11 06:37:04 +0000151 virtual void dump(raw_ostream &OS) const {}
152
Daniel Dunbar20927f22009-08-07 08:26:05 +0000153 StringRef getToken() const {
154 assert(Kind == Token && "Invalid access!");
155 return StringRef(Tok.Data, Tok.Length);
156 }
Daniel Dunbarc918d602010-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 Dunbar20927f22009-08-07 08:26:05 +0000162
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000163 unsigned getReg() const {
164 assert(Kind == Register && "Invalid access!");
165 return Reg.RegNo;
166 }
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000167
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000168 const MCExpr *getImm() const {
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000169 assert(Kind == Immediate && "Invalid access!");
170 return Imm.Val;
171 }
172
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000173 const MCExpr *getMemDisp() const {
Daniel Dunbar022e2a82009-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 Dunbara3741fa2009-08-08 07:50:56 +0000194 bool isToken() const {return Kind == Token; }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000195
196 bool isImm() const { return Kind == Immediate; }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000197
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000198 bool isImmSExti16i8() const {
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000199 if (!isImm())
200 return false;
201
Daniel Dunbar62e4c672010-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 Dunbar5fe63382009-08-09 07:20:21 +0000207
Daniel Dunbar62e4c672010-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 Dunbar5fe63382009-08-09 07:20:21 +0000214 }
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000215 bool isImmSExti32i8() const {
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000216 if (!isImm())
217 return false;
218
Daniel Dunbar62e4c672010-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 Dunbar1fe591d2010-05-20 20:20:39 +0000224
Daniel Dunbar62e4c672010-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 Dunbar1fe591d2010-05-20 20:20:39 +0000263 }
264
Daniel Dunbar20927f22009-08-07 08:26:05 +0000265 bool isMem() const { return Kind == Memory; }
266
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000267 bool isAbsMem() const {
268 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000269 !getMemIndexReg() && getMemScale() == 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000270 }
271
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000272 bool isNoSegMem() const {
273 return Kind == Memory && !getMemSegReg();
274 }
275
Daniel Dunbar20927f22009-08-07 08:26:05 +0000276 bool isReg() const { return Kind == Register; }
277
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000278 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
279 // Add as immediates when possible.
280 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
281 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
282 else
283 Inst.addOperand(MCOperand::CreateExpr(Expr));
284 }
285
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000286 void addRegOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000287 assert(N == 1 && "Invalid number of operands!");
288 Inst.addOperand(MCOperand::CreateReg(getReg()));
289 }
290
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000291 void addImmOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000292 assert(N == 1 && "Invalid number of operands!");
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000293 addExpr(Inst, getImm());
Daniel Dunbar20927f22009-08-07 08:26:05 +0000294 }
295
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000296 void addMemOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000297 assert((N == 5) && "Invalid number of operands!");
Daniel Dunbar20927f22009-08-07 08:26:05 +0000298 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
299 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
300 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000301 addExpr(Inst, getMemDisp());
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000302 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
303 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000304
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000305 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
306 assert((N == 1) && "Invalid number of operands!");
307 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
308 }
309
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000310 void addNoSegMemOperands(MCInst &Inst, unsigned N) const {
311 assert((N == 4) && "Invalid number of operands!");
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000312 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
313 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
314 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000315 addExpr(Inst, getMemDisp());
Daniel Dunbar20927f22009-08-07 08:26:05 +0000316 }
317
Chris Lattnerb4307b32010-01-15 19:28:38 +0000318 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
319 X86Operand *Res = new X86Operand(Token, Loc, Loc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000320 Res->Tok.Data = Str.data();
321 Res->Tok.Length = Str.size();
Daniel Dunbar20927f22009-08-07 08:26:05 +0000322 return Res;
323 }
324
Chris Lattner29ef9a22010-01-15 18:51:29 +0000325 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000326 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000327 Res->Reg.RegNo = RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000328 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000329 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000330
Chris Lattnerb4307b32010-01-15 19:28:38 +0000331 static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
332 X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000333 Res->Imm.Val = Val;
334 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000335 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000336
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000337 /// Create an absolute memory operand.
338 static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
339 SMLoc EndLoc) {
340 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
341 Res->Mem.SegReg = 0;
342 Res->Mem.Disp = Disp;
343 Res->Mem.BaseReg = 0;
344 Res->Mem.IndexReg = 0;
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000345 Res->Mem.Scale = 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000346 return Res;
347 }
348
349 /// Create a generalized memory operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000350 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
351 unsigned BaseReg, unsigned IndexReg,
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000352 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000353 // We should never just have a displacement, that should be parsed as an
354 // absolute memory operand.
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000355 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
356
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000357 // The scale should always be one of {1,2,4,8}.
358 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000359 "Invalid scale!");
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000360 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000361 Res->Mem.SegReg = SegReg;
362 Res->Mem.Disp = Disp;
363 Res->Mem.BaseReg = BaseReg;
364 Res->Mem.IndexReg = IndexReg;
365 Res->Mem.Scale = Scale;
366 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000367 }
368};
Daniel Dunbara3af3702009-07-20 18:55:04 +0000369
Chris Lattner37dfdec2009-07-29 06:33:53 +0000370} // end anonymous namespace.
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000371
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000372
Chris Lattner29ef9a22010-01-15 18:51:29 +0000373bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
374 SMLoc &StartLoc, SMLoc &EndLoc) {
Chris Lattner23075742010-01-15 18:27:19 +0000375 RegNo = 0;
Sean Callanan18b83232010-01-19 21:44:56 +0000376 const AsmToken &TokPercent = Parser.getTok();
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000377 assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
Chris Lattner29ef9a22010-01-15 18:51:29 +0000378 StartLoc = TokPercent.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000379 Parser.Lex(); // Eat percent token.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000380
Sean Callanan18b83232010-01-19 21:44:56 +0000381 const AsmToken &Tok = Parser.getTok();
Kevin Enderby0d6cd002009-09-16 17:18:29 +0000382 if (Tok.isNot(AsmToken::Identifier))
383 return Error(Tok.getLoc(), "invalid register name");
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000384
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000385 // FIXME: Validate register for the current architecture; we have to do
386 // validation later, so maybe there is no need for this here.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000387 RegNo = MatchRegisterName(Tok.getString());
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000388
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000389 // FIXME: This should be done using Requires<In32BitMode> and
390 // Requires<In64BitMode> so "eiz" usage in 64-bit instructions
391 // can be also checked.
392 if (RegNo == X86::RIZ && !Is64Bit)
393 return Error(Tok.getLoc(), "riz register in 64-bit mode only");
394
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000395 // Parse %st(1) and "%st" as "%st(0)"
396 if (RegNo == 0 && Tok.getString() == "st") {
397 RegNo = X86::ST0;
398 EndLoc = Tok.getLoc();
399 Parser.Lex(); // Eat 'st'
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000400
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000401 // Check to see if we have '(4)' after %st.
402 if (getLexer().isNot(AsmToken::LParen))
403 return false;
404 // Lex the paren.
405 getParser().Lex();
406
407 const AsmToken &IntTok = Parser.getTok();
408 if (IntTok.isNot(AsmToken::Integer))
409 return Error(IntTok.getLoc(), "expected stack index");
410 switch (IntTok.getIntVal()) {
411 case 0: RegNo = X86::ST0; break;
412 case 1: RegNo = X86::ST1; break;
413 case 2: RegNo = X86::ST2; break;
414 case 3: RegNo = X86::ST3; break;
415 case 4: RegNo = X86::ST4; break;
416 case 5: RegNo = X86::ST5; break;
417 case 6: RegNo = X86::ST6; break;
418 case 7: RegNo = X86::ST7; break;
419 default: return Error(IntTok.getLoc(), "invalid stack index");
420 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000421
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000422 if (getParser().Lex().isNot(AsmToken::RParen))
423 return Error(Parser.getTok().getLoc(), "expected ')'");
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000424
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000425 EndLoc = Tok.getLoc();
426 Parser.Lex(); // Eat ')'
427 return false;
428 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000429
Chris Lattner645b2092010-06-24 07:29:18 +0000430 // If this is "db[0-7]", match it as an alias
431 // for dr[0-7].
432 if (RegNo == 0 && Tok.getString().size() == 3 &&
433 Tok.getString().startswith("db")) {
434 switch (Tok.getString()[2]) {
435 case '0': RegNo = X86::DR0; break;
436 case '1': RegNo = X86::DR1; break;
437 case '2': RegNo = X86::DR2; break;
438 case '3': RegNo = X86::DR3; break;
439 case '4': RegNo = X86::DR4; break;
440 case '5': RegNo = X86::DR5; break;
441 case '6': RegNo = X86::DR6; break;
442 case '7': RegNo = X86::DR7; break;
443 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000444
Chris Lattner645b2092010-06-24 07:29:18 +0000445 if (RegNo != 0) {
446 EndLoc = Tok.getLoc();
447 Parser.Lex(); // Eat it.
448 return false;
449 }
450 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000451
Daniel Dunbar245f0582009-08-08 21:22:41 +0000452 if (RegNo == 0)
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000453 return Error(Tok.getLoc(), "invalid register name");
454
Chris Lattner29ef9a22010-01-15 18:51:29 +0000455 EndLoc = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000456 Parser.Lex(); // Eat identifier token.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000457 return false;
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000458}
459
Chris Lattner309264d2010-01-15 18:44:13 +0000460X86Operand *X86ATTAsmParser::ParseOperand() {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000461 switch (getLexer().getKind()) {
462 default:
Chris Lattnereef6d782010-04-17 18:56:34 +0000463 // Parse a memory operand with no segment register.
464 return ParseMemOperand(0, Parser.getTok().getLoc());
Chris Lattner23075742010-01-15 18:27:19 +0000465 case AsmToken::Percent: {
Chris Lattnereef6d782010-04-17 18:56:34 +0000466 // Read the register.
Chris Lattner23075742010-01-15 18:27:19 +0000467 unsigned RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000468 SMLoc Start, End;
469 if (ParseRegister(RegNo, Start, End)) return 0;
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000470 if (RegNo == X86::EIZ || RegNo == X86::RIZ) {
471 Error(Start, "eiz and riz can only be used as index registers");
472 return 0;
473 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000474
Chris Lattnereef6d782010-04-17 18:56:34 +0000475 // If this is a segment register followed by a ':', then this is the start
476 // of a memory reference, otherwise this is a normal register reference.
477 if (getLexer().isNot(AsmToken::Colon))
478 return X86Operand::CreateReg(RegNo, Start, End);
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000479
480
Chris Lattnereef6d782010-04-17 18:56:34 +0000481 getParser().Lex(); // Eat the colon.
482 return ParseMemOperand(RegNo, Start);
Chris Lattner23075742010-01-15 18:27:19 +0000483 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000484 case AsmToken::Dollar: {
485 // $42 -> immediate.
Sean Callanan18b83232010-01-19 21:44:56 +0000486 SMLoc Start = Parser.getTok().getLoc(), End;
Sean Callananb9a25b72010-01-19 20:27:46 +0000487 Parser.Lex();
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000488 const MCExpr *Val;
Chris Lattner54482b42010-01-15 19:39:23 +0000489 if (getParser().ParseExpression(Val, End))
Chris Lattner309264d2010-01-15 18:44:13 +0000490 return 0;
Chris Lattnerb4307b32010-01-15 19:28:38 +0000491 return X86Operand::CreateImm(Val, Start, End);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000492 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000493 }
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000494}
495
Chris Lattnereef6d782010-04-17 18:56:34 +0000496/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
497/// has already been parsed if present.
498X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000499
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000500 // We have to disambiguate a parenthesized expression "(4+5)" from the start
501 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
Chris Lattner75f265f2010-01-24 01:07:33 +0000502 // only way to do this without lookahead is to eat the '(' and see what is
503 // after it.
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000504 const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000505 if (getLexer().isNot(AsmToken::LParen)) {
Chris Lattner54482b42010-01-15 19:39:23 +0000506 SMLoc ExprEnd;
507 if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000508
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000509 // After parsing the base expression we could either have a parenthesized
510 // memory address or not. If not, return now. If so, eat the (.
511 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000512 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000513 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000514 return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000515 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000516 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000517
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000518 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000519 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000520 } else {
521 // Okay, we have a '('. We don't know if this is an expression or not, but
522 // so we have to eat the ( to see beyond it.
Sean Callanan18b83232010-01-19 21:44:56 +0000523 SMLoc LParenLoc = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000524 Parser.Lex(); // Eat the '('.
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000525
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000526 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000527 // Nothing to do here, fall into the code below with the '(' part of the
528 // memory operand consumed.
529 } else {
Chris Lattnerb4307b32010-01-15 19:28:38 +0000530 SMLoc ExprEnd;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000531
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000532 // It must be an parenthesized expression, parse it now.
Chris Lattnerb4307b32010-01-15 19:28:38 +0000533 if (getParser().ParseParenExpression(Disp, ExprEnd))
Chris Lattner309264d2010-01-15 18:44:13 +0000534 return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000535
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000536 // After parsing the base expression we could either have a parenthesized
537 // memory address or not. If not, return now. If so, eat the (.
538 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000539 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000540 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000541 return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000542 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000543 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000544
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000545 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000546 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000547 }
548 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000549
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000550 // If we reached here, then we just ate the ( of the memory operand. Process
551 // the rest of the memory operand.
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000552 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000553
Chris Lattner29ef9a22010-01-15 18:51:29 +0000554 if (getLexer().is(AsmToken::Percent)) {
555 SMLoc L;
556 if (ParseRegister(BaseReg, L, L)) return 0;
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000557 if (BaseReg == X86::EIZ || BaseReg == X86::RIZ) {
558 Error(L, "eiz and riz can only be used as index registers");
559 return 0;
560 }
Chris Lattner29ef9a22010-01-15 18:51:29 +0000561 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000562
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000563 if (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000564 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000565
566 // Following the comma we should have either an index register, or a scale
567 // value. We don't support the later form, but we want to parse it
568 // correctly.
569 //
570 // Not that even though it would be completely consistent to support syntax
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000571 // like "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000572 if (getLexer().is(AsmToken::Percent)) {
Chris Lattner29ef9a22010-01-15 18:51:29 +0000573 SMLoc L;
574 if (ParseRegister(IndexReg, L, L)) return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000575
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000576 if (getLexer().isNot(AsmToken::RParen)) {
577 // Parse the scale amount:
578 // ::= ',' [scale-expression]
Chris Lattner309264d2010-01-15 18:44:13 +0000579 if (getLexer().isNot(AsmToken::Comma)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000580 Error(Parser.getTok().getLoc(),
Chris Lattner309264d2010-01-15 18:44:13 +0000581 "expected comma in scale expression");
582 return 0;
583 }
Sean Callananb9a25b72010-01-19 20:27:46 +0000584 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000585
586 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000587 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000588
589 int64_t ScaleVal;
590 if (getParser().ParseAbsoluteExpression(ScaleVal))
Chris Lattner309264d2010-01-15 18:44:13 +0000591 return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000592
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000593 // Validate the scale amount.
Chris Lattner309264d2010-01-15 18:44:13 +0000594 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
595 Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
596 return 0;
597 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000598 Scale = (unsigned)ScaleVal;
599 }
600 }
601 } else if (getLexer().isNot(AsmToken::RParen)) {
602 // Otherwise we have the unsupported form of a scale amount without an
603 // index.
Sean Callanan18b83232010-01-19 21:44:56 +0000604 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000605
606 int64_t Value;
607 if (getParser().ParseAbsoluteExpression(Value))
Chris Lattner309264d2010-01-15 18:44:13 +0000608 return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000609
Chris Lattner309264d2010-01-15 18:44:13 +0000610 Error(Loc, "cannot have scale factor without index register");
611 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000612 }
613 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000614
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000615 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
Chris Lattner309264d2010-01-15 18:44:13 +0000616 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000617 Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
Chris Lattner309264d2010-01-15 18:44:13 +0000618 return 0;
619 }
Sean Callanan18b83232010-01-19 21:44:56 +0000620 SMLoc MemEnd = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000621 Parser.Lex(); // Eat the ')'.
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000622
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000623 return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
624 MemStart, MemEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000625}
626
Chris Lattner98986712010-01-14 22:21:20 +0000627bool X86ATTAsmParser::
Benjamin Kramer38e59892010-07-14 22:38:02 +0000628ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000629 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000630 // The various flavors of pushf and popf use Requires<In32BitMode> and
631 // Requires<In64BitMode>, but the assembler doesn't yet implement that.
632 // For now, just do a manual check to prevent silent misencoding.
633 if (Is64Bit) {
634 if (Name == "popfl")
635 return Error(NameLoc, "popfl cannot be encoded in 64-bit mode");
636 else if (Name == "pushfl")
637 return Error(NameLoc, "pushfl cannot be encoded in 64-bit mode");
Kevin Enderby52a18ae2010-07-13 20:05:41 +0000638 else if (Name == "pusha")
639 return Error(NameLoc, "pusha cannot be encoded in 64-bit mode");
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000640 } else {
641 if (Name == "popfq")
642 return Error(NameLoc, "popfq cannot be encoded in 32-bit mode");
643 else if (Name == "pushfq")
644 return Error(NameLoc, "pushfq cannot be encoded in 32-bit mode");
645 }
646
Kevin Enderby09712b52010-06-08 23:48:44 +0000647 // The "Jump if rCX Zero" form jcxz is not allowed in 64-bit mode and
648 // the form jrcxz is not allowed in 32-bit mode.
649 if (Is64Bit) {
650 if (Name == "jcxz")
651 return Error(NameLoc, "jcxz cannot be encoded in 64-bit mode");
652 } else {
653 if (Name == "jrcxz")
654 return Error(NameLoc, "jrcxz cannot be encoded in 32-bit mode");
655 }
656
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000657 // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
658 // represent alternative syntaxes in the .td file, without requiring
659 // instruction duplication.
660 StringRef PatchedName = StringSwitch<StringRef>(Name)
661 .Case("sal", "shl")
662 .Case("salb", "shlb")
663 .Case("sall", "shll")
664 .Case("salq", "shlq")
665 .Case("salw", "shlw")
666 .Case("repe", "rep")
667 .Case("repz", "rep")
668 .Case("repnz", "repne")
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000669 .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
670 .Case("popf", Is64Bit ? "popfq" : "popfl")
Kevin Enderby9d31d792010-05-21 23:01:38 +0000671 .Case("retl", Is64Bit ? "retl" : "ret")
672 .Case("retq", Is64Bit ? "ret" : "retq")
Daniel Dunbar4c361972010-05-22 06:37:33 +0000673 .Case("setz", "sete")
674 .Case("setnz", "setne")
675 .Case("jz", "je")
676 .Case("jnz", "jne")
Kevin Enderbybd658912010-05-27 21:33:19 +0000677 .Case("jc", "jb")
Kevin Enderby09712b52010-06-08 23:48:44 +0000678 // FIXME: in 32-bit mode jcxz requires an AdSize prefix. In 64-bit mode
679 // jecxz requires an AdSize prefix but jecxz does not have a prefix in
680 // 32-bit mode.
Kevin Enderbybd658912010-05-27 21:33:19 +0000681 .Case("jecxz", "jcxz")
Kevin Enderby09712b52010-06-08 23:48:44 +0000682 .Case("jrcxz", "jcxz")
Kevin Enderbybd658912010-05-27 21:33:19 +0000683 .Case("jna", "jbe")
684 .Case("jnae", "jb")
685 .Case("jnb", "jae")
686 .Case("jnbe", "ja")
687 .Case("jnc", "jae")
688 .Case("jng", "jle")
689 .Case("jnge", "jl")
690 .Case("jnl", "jge")
691 .Case("jnle", "jg")
692 .Case("jpe", "jp")
693 .Case("jpo", "jnp")
Kevin Enderbyca956dc2010-05-24 20:32:23 +0000694 .Case("cmovcl", "cmovbl")
695 .Case("cmovcl", "cmovbl")
696 .Case("cmovnal", "cmovbel")
697 .Case("cmovnbl", "cmovael")
698 .Case("cmovnbel", "cmoval")
699 .Case("cmovncl", "cmovael")
700 .Case("cmovngl", "cmovlel")
701 .Case("cmovnl", "cmovgel")
702 .Case("cmovngl", "cmovlel")
703 .Case("cmovngel", "cmovll")
704 .Case("cmovnll", "cmovgel")
705 .Case("cmovnlel", "cmovgl")
706 .Case("cmovnzl", "cmovnel")
707 .Case("cmovzl", "cmovel")
Kevin Enderby5e394422010-05-28 20:59:10 +0000708 .Case("fwait", "wait")
Kevin Enderby31cc9652010-05-28 21:20:21 +0000709 .Case("movzx", "movzb")
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000710 .Default(Name);
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000711
712 // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
713 const MCExpr *ExtraImmOp = 0;
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000714 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000715 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
716 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000717 bool IsVCMP = PatchedName.startswith("vcmp");
718 unsigned SSECCIdx = IsVCMP ? 4 : 3;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000719 unsigned SSEComparisonCode = StringSwitch<unsigned>(
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000720 PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
Bruno Cardoso Lopescc69e132010-07-07 22:24:03 +0000721 .Case("eq", 0)
722 .Case("lt", 1)
723 .Case("le", 2)
724 .Case("unord", 3)
725 .Case("neq", 4)
726 .Case("nlt", 5)
727 .Case("nle", 6)
728 .Case("ord", 7)
729 .Case("eq_uq", 8)
730 .Case("nge", 9)
731 .Case("ngt", 0x0A)
732 .Case("false", 0x0B)
733 .Case("neq_oq", 0x0C)
734 .Case("ge", 0x0D)
735 .Case("gt", 0x0E)
736 .Case("true", 0x0F)
737 .Case("eq_os", 0x10)
738 .Case("lt_oq", 0x11)
739 .Case("le_oq", 0x12)
740 .Case("unord_s", 0x13)
741 .Case("neq_us", 0x14)
742 .Case("nlt_uq", 0x15)
743 .Case("nle_uq", 0x16)
744 .Case("ord_s", 0x17)
745 .Case("eq_us", 0x18)
746 .Case("nge_uq", 0x19)
747 .Case("ngt_uq", 0x1A)
748 .Case("false_os", 0x1B)
749 .Case("neq_os", 0x1C)
750 .Case("ge_oq", 0x1D)
751 .Case("gt_oq", 0x1E)
752 .Case("true_us", 0x1F)
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000753 .Default(~0U);
754 if (SSEComparisonCode != ~0U) {
755 ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode,
756 getParser().getContext());
757 if (PatchedName.endswith("ss")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000758 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000759 } else if (PatchedName.endswith("sd")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000760 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000761 } else if (PatchedName.endswith("ps")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000762 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000763 } else {
764 assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000765 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000766 }
767 }
768 }
Bruno Cardoso Lopesf528d2b2010-07-23 18:41:12 +0000769
770 // FIXME: Hack to recognize vpclmul<src1_quadword, src2_quadword>dq
771 if (PatchedName.startswith("vpclmul")) {
772 unsigned CLMULQuadWordSelect = StringSwitch<unsigned>(
773 PatchedName.slice(7, PatchedName.size() - 2))
774 .Case("lqlq", 0x00) // src1[63:0], src2[63:0]
775 .Case("hqlq", 0x01) // src1[127:64], src2[63:0]
776 .Case("lqhq", 0x10) // src1[63:0], src2[127:64]
777 .Case("hqhq", 0x11) // src1[127:64], src2[127:64]
778 .Default(~0U);
779 if (CLMULQuadWordSelect != ~0U) {
780 ExtraImmOp = MCConstantExpr::Create(CLMULQuadWordSelect,
781 getParser().getContext());
782 assert(PatchedName.endswith("dq") && "Unexpected mnemonic!");
783 PatchedName = "vpclmulqdq";
784 }
785 }
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000786 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000787
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000788 if (ExtraImmOp)
789 Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
790
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000791 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000792
793 // Parse '*' modifier.
794 if (getLexer().is(AsmToken::Star)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000795 SMLoc Loc = Parser.getTok().getLoc();
Chris Lattnerb4307b32010-01-15 19:28:38 +0000796 Operands.push_back(X86Operand::CreateToken("*", Loc));
Sean Callananb9a25b72010-01-19 20:27:46 +0000797 Parser.Lex(); // Eat the star.
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000798 }
799
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000800 // Read the first operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000801 if (X86Operand *Op = ParseOperand())
802 Operands.push_back(Op);
803 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000804 return true;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000805
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000806 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000807 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000808
809 // Parse and remember the operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000810 if (X86Operand *Op = ParseOperand())
811 Operands.push_back(Op);
812 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000813 return true;
814 }
815 }
816
Daniel Dunbard5e77052010-03-13 00:47:29 +0000817 // FIXME: Hack to handle recognizing s{hr,ar,hl}? $1.
818 if ((Name.startswith("shr") || Name.startswith("sar") ||
819 Name.startswith("shl")) &&
820 Operands.size() == 3 &&
821 static_cast<X86Operand*>(Operands[1])->isImm() &&
822 isa<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm()) &&
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000823 cast<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm())->getValue() == 1) {
824 delete Operands[1];
Daniel Dunbard5e77052010-03-13 00:47:29 +0000825 Operands.erase(Operands.begin() + 1);
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000826 }
Daniel Dunbard5e77052010-03-13 00:47:29 +0000827
Kevin Enderbycf50a532010-05-25 20:52:34 +0000828 // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
829 // "f{mul*,add*,sub*,div*} $op"
830 if ((Name.startswith("fmul") || Name.startswith("fadd") ||
831 Name.startswith("fsub") || Name.startswith("fdiv")) &&
832 Operands.size() == 3 &&
833 static_cast<X86Operand*>(Operands[2])->isReg() &&
834 static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
835 delete Operands[2];
836 Operands.erase(Operands.begin() + 2);
837 }
838
Chris Lattner98986712010-01-14 22:21:20 +0000839 return false;
Daniel Dunbara3af3702009-07-20 18:55:04 +0000840}
841
Kevin Enderby9c656452009-09-10 20:51:44 +0000842bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
843 StringRef IDVal = DirectiveID.getIdentifier();
844 if (IDVal == ".word")
845 return ParseDirectiveWord(2, DirectiveID.getLoc());
846 return true;
847}
848
849/// ParseDirectiveWord
850/// ::= .word [ expression (, expression)* ]
851bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
852 if (getLexer().isNot(AsmToken::EndOfStatement)) {
853 for (;;) {
854 const MCExpr *Value;
855 if (getParser().ParseExpression(Value))
856 return true;
857
Chris Lattneraaec2052010-01-19 19:46:13 +0000858 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
Kevin Enderby9c656452009-09-10 20:51:44 +0000859
860 if (getLexer().is(AsmToken::EndOfStatement))
861 break;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000862
Kevin Enderby9c656452009-09-10 20:51:44 +0000863 // FIXME: Improve diagnostic.
864 if (getLexer().isNot(AsmToken::Comma))
865 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000866 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000867 }
868 }
869
Sean Callananb9a25b72010-01-19 20:27:46 +0000870 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000871 return false;
872}
873
Daniel Dunbarc918d602010-05-04 16:12:42 +0000874bool
875X86ATTAsmParser::MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*>
876 &Operands,
877 MCInst &Inst) {
878 // First, try a direct match.
879 if (!MatchInstructionImpl(Operands, Inst))
880 return false;
881
882 // Ignore anything which is obviously not a suffix match.
883 if (Operands.size() == 0)
884 return true;
885 X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
886 if (!Op->isToken() || Op->getToken().size() > 15)
887 return true;
888
889 // FIXME: Ideally, we would only attempt suffix matches for things which are
890 // valid prefixes, and we could just infer the right unambiguous
891 // type. However, that requires substantially more matcher support than the
892 // following hack.
893
894 // Change the operand to point to a temporary token.
895 char Tmp[16];
896 StringRef Base = Op->getToken();
897 memcpy(Tmp, Base.data(), Base.size());
898 Op->setTokenValue(StringRef(Tmp, Base.size() + 1));
899
900 // Check for the various suffix matches.
901 Tmp[Base.size()] = 'b';
902 bool MatchB = MatchInstructionImpl(Operands, Inst);
903 Tmp[Base.size()] = 'w';
904 bool MatchW = MatchInstructionImpl(Operands, Inst);
905 Tmp[Base.size()] = 'l';
906 bool MatchL = MatchInstructionImpl(Operands, Inst);
Daniel Dunbar04814492010-05-12 00:54:20 +0000907 Tmp[Base.size()] = 'q';
908 bool MatchQ = MatchInstructionImpl(Operands, Inst);
Daniel Dunbarc918d602010-05-04 16:12:42 +0000909
910 // Restore the old token.
911 Op->setTokenValue(Base);
912
913 // If exactly one matched, then we treat that as a successful match (and the
914 // instruction will already have been filled in correctly, since the failing
915 // matches won't have modified it).
Daniel Dunbar04814492010-05-12 00:54:20 +0000916 if (MatchB + MatchW + MatchL + MatchQ == 3)
Daniel Dunbarc918d602010-05-04 16:12:42 +0000917 return false;
918
Daniel Dunbarc918d602010-05-04 16:12:42 +0000919 // Otherwise, the match failed.
920 return true;
921}
922
923
Sean Callanane88f5522010-01-23 02:43:15 +0000924extern "C" void LLVMInitializeX86AsmLexer();
925
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000926// Force static initialization.
927extern "C" void LLVMInitializeX86AsmParser() {
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000928 RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
929 RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
Sean Callanane88f5522010-01-23 02:43:15 +0000930 LLVMInitializeX86AsmLexer();
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000931}
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000932
933#include "X86GenAsmMatcher.inc"