blob: 3f10b8e2f58f6266a88e0f1e08ca86841a818207 [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 Dunbarf1e29d42010-08-12 00:55:38 +000013#include "llvm/ADT/SmallString.h"
Daniel Dunbardbd692a2009-07-20 20:01:54 +000014#include "llvm/ADT/SmallVector.h"
Daniel Dunbar1b6c0602010-02-10 21:19:28 +000015#include "llvm/ADT/StringSwitch.h"
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000016#include "llvm/ADT/Twine.h"
Kevin Enderby9c656452009-09-10 20:51:44 +000017#include "llvm/MC/MCStreamer.h"
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +000018#include "llvm/MC/MCExpr.h"
Daniel Dunbara027d222009-07-31 02:32:59 +000019#include "llvm/MC/MCInst.h"
Chris Lattnerc6ef2772010-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 Dunbar16cdcb32009-07-28 22:40:46 +000023#include "llvm/Support/SourceMgr.h"
Daniel Dunbar09062b12010-08-12 00:55:42 +000024#include "llvm/Support/raw_ostream.h"
Daniel Dunbar092a9dd2009-07-17 20:42:00 +000025#include "llvm/Target/TargetRegistry.h"
26#include "llvm/Target/TargetAsmParser.h"
27using namespace llvm;
28
29namespace {
Benjamin Kramerc6b79ac2009-07-31 11:35:26 +000030struct X86Operand;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000031
32class X86ATTAsmParser : public TargetAsmParser {
33 MCAsmParser &Parser;
Daniel Dunbard73ada72010-07-19 00:33:49 +000034 TargetMachine &TM;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000035
Daniel Dunbarf98bc632010-03-18 20:06:02 +000036protected:
37 unsigned Is64Bit : 1;
38
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000039private:
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000040 MCAsmParser &getParser() const { return Parser; }
41
42 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
43
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000044 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
Daniel Dunbarf1e29d42010-08-12 00:55:38 +000053 bool MatchInstruction(SMLoc IDLoc,
54 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbar20927f22009-08-07 08:26:05 +000055 MCInst &Inst);
56
Daniel Dunbar54074b52010-07-19 05:44:09 +000057 /// @name Auto-generated Matcher Functions
58 /// {
59
60 unsigned ComputeAvailableFeatures(const X86Subtarget *Subtarget) const;
61
Daniel Dunbarc918d602010-05-04 16:12:42 +000062 bool MatchInstructionImpl(
63 const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst);
64
Daniel Dunbar0e2771f2009-07-29 00:02:19 +000065 /// }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000066
67public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000068 X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
Daniel Dunbar54074b52010-07-19 05:44:09 +000069 : TargetAsmParser(T), Parser(_Parser), TM(TM) {
70
71 // Initialize the set of available features.
72 setAvailableFeatures(ComputeAvailableFeatures(
73 &TM.getSubtarget<X86Subtarget>()));
74 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000075
Benjamin Kramer38e59892010-07-14 22:38:02 +000076 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +000077 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderby9c656452009-09-10 20:51:44 +000078
79 virtual bool ParseDirective(AsmToken DirectiveID);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000080};
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +000081
Daniel Dunbarf98bc632010-03-18 20:06:02 +000082class X86_32ATTAsmParser : public X86ATTAsmParser {
83public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000084 X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
85 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbarf98bc632010-03-18 20:06:02 +000086 Is64Bit = false;
87 }
88};
89
90class X86_64ATTAsmParser : public X86ATTAsmParser {
91public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000092 X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
93 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbarf98bc632010-03-18 20:06:02 +000094 Is64Bit = true;
95 }
96};
97
Chris Lattner37dfdec2009-07-29 06:33:53 +000098} // end anonymous namespace
99
Sean Callanane9b466d2010-01-23 00:40:33 +0000100/// @name Auto-generated Match Functions
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000101/// {
Sean Callanane9b466d2010-01-23 00:40:33 +0000102
Chris Lattnerb8d6e982010-02-09 00:34:28 +0000103static unsigned MatchRegisterName(StringRef Name);
Sean Callanane9b466d2010-01-23 00:40:33 +0000104
105/// }
Chris Lattner37dfdec2009-07-29 06:33:53 +0000106
107namespace {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000108
109/// X86Operand - Instances of this class represent a parsed X86 machine
110/// instruction.
Chris Lattner45220a82010-01-14 21:20:55 +0000111struct X86Operand : public MCParsedAsmOperand {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000112 enum KindTy {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000113 Token,
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000114 Register,
115 Immediate,
116 Memory
117 } Kind;
118
Chris Lattner29ef9a22010-01-15 18:51:29 +0000119 SMLoc StartLoc, EndLoc;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000120
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000121 union {
122 struct {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000123 const char *Data;
124 unsigned Length;
125 } Tok;
126
127 struct {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000128 unsigned RegNo;
129 } Reg;
130
131 struct {
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000132 const MCExpr *Val;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000133 } Imm;
134
135 struct {
136 unsigned SegReg;
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000137 const MCExpr *Disp;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000138 unsigned BaseReg;
139 unsigned IndexReg;
140 unsigned Scale;
141 } Mem;
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000142 };
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000143
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000144 X86Operand(KindTy K, SMLoc Start, SMLoc End)
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000145 : Kind(K), StartLoc(Start), EndLoc(End) {}
Daniel Dunbarc918d602010-05-04 16:12:42 +0000146
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000147 /// getStartLoc - Get the location of the first token of this operand.
148 SMLoc getStartLoc() const { return StartLoc; }
149 /// getEndLoc - Get the location of the last token of this operand.
150 SMLoc getEndLoc() const { return EndLoc; }
151
Daniel Dunbarb3cb6962010-08-11 06:37:04 +0000152 virtual void dump(raw_ostream &OS) const {}
153
Daniel Dunbar20927f22009-08-07 08:26:05 +0000154 StringRef getToken() const {
155 assert(Kind == Token && "Invalid access!");
156 return StringRef(Tok.Data, Tok.Length);
157 }
Daniel Dunbarc918d602010-05-04 16:12:42 +0000158 void setTokenValue(StringRef Value) {
159 assert(Kind == Token && "Invalid access!");
160 Tok.Data = Value.data();
161 Tok.Length = Value.size();
162 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000163
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000164 unsigned getReg() const {
165 assert(Kind == Register && "Invalid access!");
166 return Reg.RegNo;
167 }
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000168
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000169 const MCExpr *getImm() const {
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000170 assert(Kind == Immediate && "Invalid access!");
171 return Imm.Val;
172 }
173
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000174 const MCExpr *getMemDisp() const {
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000175 assert(Kind == Memory && "Invalid access!");
176 return Mem.Disp;
177 }
178 unsigned getMemSegReg() const {
179 assert(Kind == Memory && "Invalid access!");
180 return Mem.SegReg;
181 }
182 unsigned getMemBaseReg() const {
183 assert(Kind == Memory && "Invalid access!");
184 return Mem.BaseReg;
185 }
186 unsigned getMemIndexReg() const {
187 assert(Kind == Memory && "Invalid access!");
188 return Mem.IndexReg;
189 }
190 unsigned getMemScale() const {
191 assert(Kind == Memory && "Invalid access!");
192 return Mem.Scale;
193 }
194
Daniel Dunbara3741fa2009-08-08 07:50:56 +0000195 bool isToken() const {return Kind == Token; }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000196
197 bool isImm() const { return Kind == Immediate; }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000198
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000199 bool isImmSExti16i8() const {
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000200 if (!isImm())
201 return false;
202
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000203 // If this isn't a constant expr, just assume it fits and let relaxation
204 // handle it.
205 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
206 if (!CE)
207 return true;
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000208
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000209 // Otherwise, check the value is in a range that makes sense for this
210 // extension.
211 uint64_t Value = CE->getValue();
212 return (( Value <= 0x000000000000007FULL)||
213 (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)||
214 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000215 }
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000216 bool isImmSExti32i8() const {
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000217 if (!isImm())
218 return false;
219
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000220 // If this isn't a constant expr, just assume it fits and let relaxation
221 // handle it.
222 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
223 if (!CE)
224 return true;
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000225
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000226 // Otherwise, check the value is in a range that makes sense for this
227 // extension.
228 uint64_t Value = CE->getValue();
229 return (( Value <= 0x000000000000007FULL)||
230 (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
231 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
232 }
233 bool isImmSExti64i8() const {
234 if (!isImm())
235 return false;
236
237 // If this isn't a constant expr, just assume it fits and let relaxation
238 // handle it.
239 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
240 if (!CE)
241 return true;
242
243 // Otherwise, check the value is in a range that makes sense for this
244 // extension.
245 uint64_t Value = CE->getValue();
246 return (( Value <= 0x000000000000007FULL)||
247 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
248 }
249 bool isImmSExti64i32() const {
250 if (!isImm())
251 return false;
252
253 // If this isn't a constant expr, just assume it fits and let relaxation
254 // handle it.
255 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
256 if (!CE)
257 return true;
258
259 // Otherwise, check the value is in a range that makes sense for this
260 // extension.
261 uint64_t Value = CE->getValue();
262 return (( Value <= 0x000000007FFFFFFFULL)||
263 (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000264 }
265
Daniel Dunbar20927f22009-08-07 08:26:05 +0000266 bool isMem() const { return Kind == Memory; }
267
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000268 bool isAbsMem() const {
269 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000270 !getMemIndexReg() && getMemScale() == 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000271 }
272
Daniel Dunbar20927f22009-08-07 08:26:05 +0000273 bool isReg() const { return Kind == Register; }
274
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000275 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
276 // Add as immediates when possible.
277 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
278 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
279 else
280 Inst.addOperand(MCOperand::CreateExpr(Expr));
281 }
282
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000283 void addRegOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000284 assert(N == 1 && "Invalid number of operands!");
285 Inst.addOperand(MCOperand::CreateReg(getReg()));
286 }
287
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000288 void addImmOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000289 assert(N == 1 && "Invalid number of operands!");
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000290 addExpr(Inst, getImm());
Daniel Dunbar20927f22009-08-07 08:26:05 +0000291 }
292
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000293 void addMemOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000294 assert((N == 5) && "Invalid number of operands!");
Daniel Dunbar20927f22009-08-07 08:26:05 +0000295 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
296 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
297 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000298 addExpr(Inst, getMemDisp());
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000299 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
300 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000301
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000302 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
303 assert((N == 1) && "Invalid number of operands!");
304 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
305 }
306
Chris Lattnerb4307b32010-01-15 19:28:38 +0000307 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
308 X86Operand *Res = new X86Operand(Token, Loc, Loc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000309 Res->Tok.Data = Str.data();
310 Res->Tok.Length = Str.size();
Daniel Dunbar20927f22009-08-07 08:26:05 +0000311 return Res;
312 }
313
Chris Lattner29ef9a22010-01-15 18:51:29 +0000314 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000315 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000316 Res->Reg.RegNo = RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000317 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000318 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000319
Chris Lattnerb4307b32010-01-15 19:28:38 +0000320 static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
321 X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000322 Res->Imm.Val = Val;
323 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000324 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000325
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000326 /// Create an absolute memory operand.
327 static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
328 SMLoc EndLoc) {
329 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
330 Res->Mem.SegReg = 0;
331 Res->Mem.Disp = Disp;
332 Res->Mem.BaseReg = 0;
333 Res->Mem.IndexReg = 0;
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000334 Res->Mem.Scale = 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000335 return Res;
336 }
337
338 /// Create a generalized memory operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000339 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
340 unsigned BaseReg, unsigned IndexReg,
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000341 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000342 // We should never just have a displacement, that should be parsed as an
343 // absolute memory operand.
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000344 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
345
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000346 // The scale should always be one of {1,2,4,8}.
347 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000348 "Invalid scale!");
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000349 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000350 Res->Mem.SegReg = SegReg;
351 Res->Mem.Disp = Disp;
352 Res->Mem.BaseReg = BaseReg;
353 Res->Mem.IndexReg = IndexReg;
354 Res->Mem.Scale = Scale;
355 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000356 }
357};
Daniel Dunbara3af3702009-07-20 18:55:04 +0000358
Chris Lattner37dfdec2009-07-29 06:33:53 +0000359} // end anonymous namespace.
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000360
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000361
Chris Lattner29ef9a22010-01-15 18:51:29 +0000362bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
363 SMLoc &StartLoc, SMLoc &EndLoc) {
Chris Lattner23075742010-01-15 18:27:19 +0000364 RegNo = 0;
Sean Callanan18b83232010-01-19 21:44:56 +0000365 const AsmToken &TokPercent = Parser.getTok();
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000366 assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
Chris Lattner29ef9a22010-01-15 18:51:29 +0000367 StartLoc = TokPercent.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000368 Parser.Lex(); // Eat percent token.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000369
Sean Callanan18b83232010-01-19 21:44:56 +0000370 const AsmToken &Tok = Parser.getTok();
Kevin Enderby0d6cd002009-09-16 17:18:29 +0000371 if (Tok.isNot(AsmToken::Identifier))
372 return Error(Tok.getLoc(), "invalid register name");
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000373
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000374 // FIXME: Validate register for the current architecture; we have to do
375 // validation later, so maybe there is no need for this here.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000376 RegNo = MatchRegisterName(Tok.getString());
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000377
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000378 // FIXME: This should be done using Requires<In32BitMode> and
379 // Requires<In64BitMode> so "eiz" usage in 64-bit instructions
380 // can be also checked.
381 if (RegNo == X86::RIZ && !Is64Bit)
382 return Error(Tok.getLoc(), "riz register in 64-bit mode only");
383
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000384 // Parse %st(1) and "%st" as "%st(0)"
385 if (RegNo == 0 && Tok.getString() == "st") {
386 RegNo = X86::ST0;
387 EndLoc = Tok.getLoc();
388 Parser.Lex(); // Eat 'st'
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000389
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000390 // Check to see if we have '(4)' after %st.
391 if (getLexer().isNot(AsmToken::LParen))
392 return false;
393 // Lex the paren.
394 getParser().Lex();
395
396 const AsmToken &IntTok = Parser.getTok();
397 if (IntTok.isNot(AsmToken::Integer))
398 return Error(IntTok.getLoc(), "expected stack index");
399 switch (IntTok.getIntVal()) {
400 case 0: RegNo = X86::ST0; break;
401 case 1: RegNo = X86::ST1; break;
402 case 2: RegNo = X86::ST2; break;
403 case 3: RegNo = X86::ST3; break;
404 case 4: RegNo = X86::ST4; break;
405 case 5: RegNo = X86::ST5; break;
406 case 6: RegNo = X86::ST6; break;
407 case 7: RegNo = X86::ST7; break;
408 default: return Error(IntTok.getLoc(), "invalid stack index");
409 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000410
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000411 if (getParser().Lex().isNot(AsmToken::RParen))
412 return Error(Parser.getTok().getLoc(), "expected ')'");
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000413
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000414 EndLoc = Tok.getLoc();
415 Parser.Lex(); // Eat ')'
416 return false;
417 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000418
Chris Lattner645b2092010-06-24 07:29:18 +0000419 // If this is "db[0-7]", match it as an alias
420 // for dr[0-7].
421 if (RegNo == 0 && Tok.getString().size() == 3 &&
422 Tok.getString().startswith("db")) {
423 switch (Tok.getString()[2]) {
424 case '0': RegNo = X86::DR0; break;
425 case '1': RegNo = X86::DR1; break;
426 case '2': RegNo = X86::DR2; break;
427 case '3': RegNo = X86::DR3; break;
428 case '4': RegNo = X86::DR4; break;
429 case '5': RegNo = X86::DR5; break;
430 case '6': RegNo = X86::DR6; break;
431 case '7': RegNo = X86::DR7; break;
432 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000433
Chris Lattner645b2092010-06-24 07:29:18 +0000434 if (RegNo != 0) {
435 EndLoc = Tok.getLoc();
436 Parser.Lex(); // Eat it.
437 return false;
438 }
439 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000440
Daniel Dunbar245f0582009-08-08 21:22:41 +0000441 if (RegNo == 0)
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000442 return Error(Tok.getLoc(), "invalid register name");
443
Chris Lattner29ef9a22010-01-15 18:51:29 +0000444 EndLoc = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000445 Parser.Lex(); // Eat identifier token.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000446 return false;
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000447}
448
Chris Lattner309264d2010-01-15 18:44:13 +0000449X86Operand *X86ATTAsmParser::ParseOperand() {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000450 switch (getLexer().getKind()) {
451 default:
Chris Lattnereef6d782010-04-17 18:56:34 +0000452 // Parse a memory operand with no segment register.
453 return ParseMemOperand(0, Parser.getTok().getLoc());
Chris Lattner23075742010-01-15 18:27:19 +0000454 case AsmToken::Percent: {
Chris Lattnereef6d782010-04-17 18:56:34 +0000455 // Read the register.
Chris Lattner23075742010-01-15 18:27:19 +0000456 unsigned RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000457 SMLoc Start, End;
458 if (ParseRegister(RegNo, Start, End)) return 0;
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000459 if (RegNo == X86::EIZ || RegNo == X86::RIZ) {
460 Error(Start, "eiz and riz can only be used as index registers");
461 return 0;
462 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000463
Chris Lattnereef6d782010-04-17 18:56:34 +0000464 // If this is a segment register followed by a ':', then this is the start
465 // of a memory reference, otherwise this is a normal register reference.
466 if (getLexer().isNot(AsmToken::Colon))
467 return X86Operand::CreateReg(RegNo, Start, End);
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000468
469
Chris Lattnereef6d782010-04-17 18:56:34 +0000470 getParser().Lex(); // Eat the colon.
471 return ParseMemOperand(RegNo, Start);
Chris Lattner23075742010-01-15 18:27:19 +0000472 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000473 case AsmToken::Dollar: {
474 // $42 -> immediate.
Sean Callanan18b83232010-01-19 21:44:56 +0000475 SMLoc Start = Parser.getTok().getLoc(), End;
Sean Callananb9a25b72010-01-19 20:27:46 +0000476 Parser.Lex();
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000477 const MCExpr *Val;
Chris Lattner54482b42010-01-15 19:39:23 +0000478 if (getParser().ParseExpression(Val, End))
Chris Lattner309264d2010-01-15 18:44:13 +0000479 return 0;
Chris Lattnerb4307b32010-01-15 19:28:38 +0000480 return X86Operand::CreateImm(Val, Start, End);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000481 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000482 }
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000483}
484
Chris Lattnereef6d782010-04-17 18:56:34 +0000485/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
486/// has already been parsed if present.
487X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000488
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000489 // We have to disambiguate a parenthesized expression "(4+5)" from the start
490 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
Chris Lattner75f265f2010-01-24 01:07:33 +0000491 // only way to do this without lookahead is to eat the '(' and see what is
492 // after it.
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000493 const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000494 if (getLexer().isNot(AsmToken::LParen)) {
Chris Lattner54482b42010-01-15 19:39:23 +0000495 SMLoc ExprEnd;
496 if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000497
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000498 // After parsing the base expression we could either have a parenthesized
499 // memory address or not. If not, return now. If so, eat the (.
500 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000501 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000502 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000503 return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000504 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000505 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000506
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000507 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000508 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000509 } else {
510 // Okay, we have a '('. We don't know if this is an expression or not, but
511 // so we have to eat the ( to see beyond it.
Sean Callanan18b83232010-01-19 21:44:56 +0000512 SMLoc LParenLoc = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000513 Parser.Lex(); // Eat the '('.
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000514
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000515 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000516 // Nothing to do here, fall into the code below with the '(' part of the
517 // memory operand consumed.
518 } else {
Chris Lattnerb4307b32010-01-15 19:28:38 +0000519 SMLoc ExprEnd;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000520
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000521 // It must be an parenthesized expression, parse it now.
Chris Lattnerb4307b32010-01-15 19:28:38 +0000522 if (getParser().ParseParenExpression(Disp, ExprEnd))
Chris Lattner309264d2010-01-15 18:44:13 +0000523 return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000524
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000525 // After parsing the base expression we could either have a parenthesized
526 // memory address or not. If not, return now. If so, eat the (.
527 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000528 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000529 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000530 return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000531 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000532 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000533
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000534 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000535 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000536 }
537 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000538
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000539 // If we reached here, then we just ate the ( of the memory operand. Process
540 // the rest of the memory operand.
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000541 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000542
Chris Lattner29ef9a22010-01-15 18:51:29 +0000543 if (getLexer().is(AsmToken::Percent)) {
544 SMLoc L;
545 if (ParseRegister(BaseReg, L, L)) return 0;
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000546 if (BaseReg == X86::EIZ || BaseReg == X86::RIZ) {
547 Error(L, "eiz and riz can only be used as index registers");
548 return 0;
549 }
Chris Lattner29ef9a22010-01-15 18:51:29 +0000550 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000551
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000552 if (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000553 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000554
555 // Following the comma we should have either an index register, or a scale
556 // value. We don't support the later form, but we want to parse it
557 // correctly.
558 //
559 // Not that even though it would be completely consistent to support syntax
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000560 // like "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000561 if (getLexer().is(AsmToken::Percent)) {
Chris Lattner29ef9a22010-01-15 18:51:29 +0000562 SMLoc L;
563 if (ParseRegister(IndexReg, L, L)) return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000564
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000565 if (getLexer().isNot(AsmToken::RParen)) {
566 // Parse the scale amount:
567 // ::= ',' [scale-expression]
Chris Lattner309264d2010-01-15 18:44:13 +0000568 if (getLexer().isNot(AsmToken::Comma)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000569 Error(Parser.getTok().getLoc(),
Chris Lattner309264d2010-01-15 18:44:13 +0000570 "expected comma in scale expression");
571 return 0;
572 }
Sean Callananb9a25b72010-01-19 20:27:46 +0000573 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000574
575 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000576 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000577
578 int64_t ScaleVal;
579 if (getParser().ParseAbsoluteExpression(ScaleVal))
Chris Lattner309264d2010-01-15 18:44:13 +0000580 return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000581
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000582 // Validate the scale amount.
Chris Lattner309264d2010-01-15 18:44:13 +0000583 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
584 Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
585 return 0;
586 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000587 Scale = (unsigned)ScaleVal;
588 }
589 }
590 } else if (getLexer().isNot(AsmToken::RParen)) {
Daniel Dunbaree910252010-08-24 19:13:38 +0000591 // A scale amount without an index is ignored.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000592 // index.
Sean Callanan18b83232010-01-19 21:44:56 +0000593 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000594
595 int64_t Value;
596 if (getParser().ParseAbsoluteExpression(Value))
Chris Lattner309264d2010-01-15 18:44:13 +0000597 return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000598
Daniel Dunbaree910252010-08-24 19:13:38 +0000599 if (Value != 1)
600 Warning(Loc, "scale factor without index register is ignored");
601 Scale = 1;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000602 }
603 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000604
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000605 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
Chris Lattner309264d2010-01-15 18:44:13 +0000606 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000607 Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
Chris Lattner309264d2010-01-15 18:44:13 +0000608 return 0;
609 }
Sean Callanan18b83232010-01-19 21:44:56 +0000610 SMLoc MemEnd = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000611 Parser.Lex(); // Eat the ')'.
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000612
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000613 return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
614 MemStart, MemEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000615}
616
Chris Lattner98986712010-01-14 22:21:20 +0000617bool X86ATTAsmParser::
Benjamin Kramer38e59892010-07-14 22:38:02 +0000618ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000619 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000620 // The various flavors of pushf and popf use Requires<In32BitMode> and
621 // Requires<In64BitMode>, but the assembler doesn't yet implement that.
622 // For now, just do a manual check to prevent silent misencoding.
623 if (Is64Bit) {
624 if (Name == "popfl")
625 return Error(NameLoc, "popfl cannot be encoded in 64-bit mode");
626 else if (Name == "pushfl")
627 return Error(NameLoc, "pushfl cannot be encoded in 64-bit mode");
Kevin Enderby52a18ae2010-07-13 20:05:41 +0000628 else if (Name == "pusha")
629 return Error(NameLoc, "pusha cannot be encoded in 64-bit mode");
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000630 } else {
631 if (Name == "popfq")
632 return Error(NameLoc, "popfq cannot be encoded in 32-bit mode");
633 else if (Name == "pushfq")
634 return Error(NameLoc, "pushfq cannot be encoded in 32-bit mode");
635 }
636
Kevin Enderby09712b52010-06-08 23:48:44 +0000637 // The "Jump if rCX Zero" form jcxz is not allowed in 64-bit mode and
638 // the form jrcxz is not allowed in 32-bit mode.
639 if (Is64Bit) {
640 if (Name == "jcxz")
641 return Error(NameLoc, "jcxz cannot be encoded in 64-bit mode");
642 } else {
643 if (Name == "jrcxz")
644 return Error(NameLoc, "jrcxz cannot be encoded in 32-bit mode");
645 }
646
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000647 // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
648 // represent alternative syntaxes in the .td file, without requiring
649 // instruction duplication.
650 StringRef PatchedName = StringSwitch<StringRef>(Name)
651 .Case("sal", "shl")
652 .Case("salb", "shlb")
653 .Case("sall", "shll")
654 .Case("salq", "shlq")
655 .Case("salw", "shlw")
656 .Case("repe", "rep")
657 .Case("repz", "rep")
658 .Case("repnz", "repne")
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000659 .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
660 .Case("popf", Is64Bit ? "popfq" : "popfl")
Kevin Enderby9d31d792010-05-21 23:01:38 +0000661 .Case("retl", Is64Bit ? "retl" : "ret")
662 .Case("retq", Is64Bit ? "ret" : "retq")
Daniel Dunbar4c361972010-05-22 06:37:33 +0000663 .Case("setz", "sete")
664 .Case("setnz", "setne")
665 .Case("jz", "je")
666 .Case("jnz", "jne")
Kevin Enderbybd658912010-05-27 21:33:19 +0000667 .Case("jc", "jb")
Kevin Enderby09712b52010-06-08 23:48:44 +0000668 // FIXME: in 32-bit mode jcxz requires an AdSize prefix. In 64-bit mode
669 // jecxz requires an AdSize prefix but jecxz does not have a prefix in
670 // 32-bit mode.
Kevin Enderbybd658912010-05-27 21:33:19 +0000671 .Case("jecxz", "jcxz")
Kevin Enderby09712b52010-06-08 23:48:44 +0000672 .Case("jrcxz", "jcxz")
Kevin Enderbybd658912010-05-27 21:33:19 +0000673 .Case("jna", "jbe")
674 .Case("jnae", "jb")
675 .Case("jnb", "jae")
676 .Case("jnbe", "ja")
677 .Case("jnc", "jae")
678 .Case("jng", "jle")
679 .Case("jnge", "jl")
680 .Case("jnl", "jge")
681 .Case("jnle", "jg")
682 .Case("jpe", "jp")
683 .Case("jpo", "jnp")
Kevin Enderbyca956dc2010-05-24 20:32:23 +0000684 .Case("cmovcl", "cmovbl")
685 .Case("cmovcl", "cmovbl")
686 .Case("cmovnal", "cmovbel")
687 .Case("cmovnbl", "cmovael")
688 .Case("cmovnbel", "cmoval")
689 .Case("cmovncl", "cmovael")
690 .Case("cmovngl", "cmovlel")
691 .Case("cmovnl", "cmovgel")
692 .Case("cmovngl", "cmovlel")
693 .Case("cmovngel", "cmovll")
694 .Case("cmovnll", "cmovgel")
695 .Case("cmovnlel", "cmovgl")
696 .Case("cmovnzl", "cmovnel")
697 .Case("cmovzl", "cmovel")
Kevin Enderby5e394422010-05-28 20:59:10 +0000698 .Case("fwait", "wait")
Kevin Enderby31cc9652010-05-28 21:20:21 +0000699 .Case("movzx", "movzb")
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000700 .Default(Name);
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000701
702 // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
703 const MCExpr *ExtraImmOp = 0;
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000704 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000705 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
706 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000707 bool IsVCMP = PatchedName.startswith("vcmp");
708 unsigned SSECCIdx = IsVCMP ? 4 : 3;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000709 unsigned SSEComparisonCode = StringSwitch<unsigned>(
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000710 PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
Bruno Cardoso Lopescc69e132010-07-07 22:24:03 +0000711 .Case("eq", 0)
712 .Case("lt", 1)
713 .Case("le", 2)
714 .Case("unord", 3)
715 .Case("neq", 4)
716 .Case("nlt", 5)
717 .Case("nle", 6)
718 .Case("ord", 7)
719 .Case("eq_uq", 8)
720 .Case("nge", 9)
721 .Case("ngt", 0x0A)
722 .Case("false", 0x0B)
723 .Case("neq_oq", 0x0C)
724 .Case("ge", 0x0D)
725 .Case("gt", 0x0E)
726 .Case("true", 0x0F)
727 .Case("eq_os", 0x10)
728 .Case("lt_oq", 0x11)
729 .Case("le_oq", 0x12)
730 .Case("unord_s", 0x13)
731 .Case("neq_us", 0x14)
732 .Case("nlt_uq", 0x15)
733 .Case("nle_uq", 0x16)
734 .Case("ord_s", 0x17)
735 .Case("eq_us", 0x18)
736 .Case("nge_uq", 0x19)
737 .Case("ngt_uq", 0x1A)
738 .Case("false_os", 0x1B)
739 .Case("neq_os", 0x1C)
740 .Case("ge_oq", 0x1D)
741 .Case("gt_oq", 0x1E)
742 .Case("true_us", 0x1F)
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000743 .Default(~0U);
744 if (SSEComparisonCode != ~0U) {
745 ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode,
746 getParser().getContext());
747 if (PatchedName.endswith("ss")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000748 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000749 } else if (PatchedName.endswith("sd")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000750 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000751 } else if (PatchedName.endswith("ps")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000752 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000753 } else {
754 assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000755 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000756 }
757 }
758 }
Bruno Cardoso Lopesf528d2b2010-07-23 18:41:12 +0000759
760 // FIXME: Hack to recognize vpclmul<src1_quadword, src2_quadword>dq
761 if (PatchedName.startswith("vpclmul")) {
762 unsigned CLMULQuadWordSelect = StringSwitch<unsigned>(
763 PatchedName.slice(7, PatchedName.size() - 2))
764 .Case("lqlq", 0x00) // src1[63:0], src2[63:0]
765 .Case("hqlq", 0x01) // src1[127:64], src2[63:0]
766 .Case("lqhq", 0x10) // src1[63:0], src2[127:64]
767 .Case("hqhq", 0x11) // src1[127:64], src2[127:64]
768 .Default(~0U);
769 if (CLMULQuadWordSelect != ~0U) {
770 ExtraImmOp = MCConstantExpr::Create(CLMULQuadWordSelect,
771 getParser().getContext());
772 assert(PatchedName.endswith("dq") && "Unexpected mnemonic!");
773 PatchedName = "vpclmulqdq";
774 }
775 }
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000776 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000777
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000778 if (ExtraImmOp)
779 Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
780
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000781 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000782
783 // Parse '*' modifier.
784 if (getLexer().is(AsmToken::Star)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000785 SMLoc Loc = Parser.getTok().getLoc();
Chris Lattnerb4307b32010-01-15 19:28:38 +0000786 Operands.push_back(X86Operand::CreateToken("*", Loc));
Sean Callananb9a25b72010-01-19 20:27:46 +0000787 Parser.Lex(); // Eat the star.
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000788 }
789
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000790 // Read the first operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000791 if (X86Operand *Op = ParseOperand())
792 Operands.push_back(Op);
793 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000794 return true;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000795
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000796 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000797 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000798
799 // Parse and remember the operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000800 if (X86Operand *Op = ParseOperand())
801 Operands.push_back(Op);
802 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000803 return true;
804 }
805 }
806
Daniel Dunbard5e77052010-03-13 00:47:29 +0000807 // FIXME: Hack to handle recognizing s{hr,ar,hl}? $1.
808 if ((Name.startswith("shr") || Name.startswith("sar") ||
809 Name.startswith("shl")) &&
810 Operands.size() == 3 &&
811 static_cast<X86Operand*>(Operands[1])->isImm() &&
812 isa<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm()) &&
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000813 cast<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm())->getValue() == 1) {
814 delete Operands[1];
Daniel Dunbard5e77052010-03-13 00:47:29 +0000815 Operands.erase(Operands.begin() + 1);
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000816 }
Daniel Dunbard5e77052010-03-13 00:47:29 +0000817
Kevin Enderbycf50a532010-05-25 20:52:34 +0000818 // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
819 // "f{mul*,add*,sub*,div*} $op"
820 if ((Name.startswith("fmul") || Name.startswith("fadd") ||
821 Name.startswith("fsub") || Name.startswith("fdiv")) &&
822 Operands.size() == 3 &&
823 static_cast<X86Operand*>(Operands[2])->isReg() &&
824 static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
825 delete Operands[2];
826 Operands.erase(Operands.begin() + 2);
827 }
828
Daniel Dunbarae528f62010-08-24 19:24:18 +0000829 // FIXME: Hack to handle "imul A, B" which is an alias for "imul A, B, B".
830 if (Name.startswith("imul") && Operands.size() == 3 &&
831 static_cast<X86Operand*>(Operands.back())->isReg()) {
832 X86Operand *Op = static_cast<X86Operand*>(Operands.back());
833 Operands.push_back(X86Operand::CreateReg(Op->getReg(), Op->getStartLoc(),
834 Op->getEndLoc()));
835 }
836
Chris Lattner98986712010-01-14 22:21:20 +0000837 return false;
Daniel Dunbara3af3702009-07-20 18:55:04 +0000838}
839
Kevin Enderby9c656452009-09-10 20:51:44 +0000840bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
841 StringRef IDVal = DirectiveID.getIdentifier();
842 if (IDVal == ".word")
843 return ParseDirectiveWord(2, DirectiveID.getLoc());
844 return true;
845}
846
847/// ParseDirectiveWord
848/// ::= .word [ expression (, expression)* ]
849bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
850 if (getLexer().isNot(AsmToken::EndOfStatement)) {
851 for (;;) {
852 const MCExpr *Value;
853 if (getParser().ParseExpression(Value))
854 return true;
855
Chris Lattneraaec2052010-01-19 19:46:13 +0000856 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
Kevin Enderby9c656452009-09-10 20:51:44 +0000857
858 if (getLexer().is(AsmToken::EndOfStatement))
859 break;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000860
Kevin Enderby9c656452009-09-10 20:51:44 +0000861 // FIXME: Improve diagnostic.
862 if (getLexer().isNot(AsmToken::Comma))
863 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000864 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000865 }
866 }
867
Sean Callananb9a25b72010-01-19 20:27:46 +0000868 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000869 return false;
870}
871
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000872
Daniel Dunbarc918d602010-05-04 16:12:42 +0000873bool
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000874X86ATTAsmParser::MatchInstruction(SMLoc IDLoc,
875 const SmallVectorImpl<MCParsedAsmOperand*>
Daniel Dunbarc918d602010-05-04 16:12:42 +0000876 &Operands,
877 MCInst &Inst) {
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000878 assert(!Operands.empty() && "Unexpect empty operand list!");
879
880 X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
881 assert(Op->isToken() && "Leading operand should always be a mnemonic!");
882
Daniel Dunbarc918d602010-05-04 16:12:42 +0000883 // First, try a direct match.
884 if (!MatchInstructionImpl(Operands, Inst))
885 return false;
886
Daniel Dunbarc918d602010-05-04 16:12:42 +0000887 // FIXME: Ideally, we would only attempt suffix matches for things which are
888 // valid prefixes, and we could just infer the right unambiguous
889 // type. However, that requires substantially more matcher support than the
890 // following hack.
891
892 // Change the operand to point to a temporary token.
Daniel Dunbarc918d602010-05-04 16:12:42 +0000893 StringRef Base = Op->getToken();
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000894 SmallString<16> Tmp;
895 Tmp += Base;
896 Tmp += ' ';
897 Op->setTokenValue(Tmp.str());
Daniel Dunbarc918d602010-05-04 16:12:42 +0000898
899 // Check for the various suffix matches.
900 Tmp[Base.size()] = 'b';
901 bool MatchB = MatchInstructionImpl(Operands, Inst);
902 Tmp[Base.size()] = 'w';
903 bool MatchW = MatchInstructionImpl(Operands, Inst);
904 Tmp[Base.size()] = 'l';
905 bool MatchL = MatchInstructionImpl(Operands, Inst);
Daniel Dunbar04814492010-05-12 00:54:20 +0000906 Tmp[Base.size()] = 'q';
907 bool MatchQ = MatchInstructionImpl(Operands, Inst);
Daniel Dunbarc918d602010-05-04 16:12:42 +0000908
909 // Restore the old token.
910 Op->setTokenValue(Base);
911
912 // If exactly one matched, then we treat that as a successful match (and the
913 // instruction will already have been filled in correctly, since the failing
914 // matches won't have modified it).
Daniel Dunbar04814492010-05-12 00:54:20 +0000915 if (MatchB + MatchW + MatchL + MatchQ == 3)
Daniel Dunbarc918d602010-05-04 16:12:42 +0000916 return false;
917
Daniel Dunbarc918d602010-05-04 16:12:42 +0000918 // Otherwise, the match failed.
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000919
Daniel Dunbar09062b12010-08-12 00:55:42 +0000920 // If we had multiple suffix matches, then identify this as an ambiguous
921 // match.
922 if (MatchB + MatchW + MatchL + MatchQ != 4) {
923 char MatchChars[4];
924 unsigned NumMatches = 0;
925 if (!MatchB)
926 MatchChars[NumMatches++] = 'b';
927 if (!MatchW)
928 MatchChars[NumMatches++] = 'w';
929 if (!MatchL)
930 MatchChars[NumMatches++] = 'l';
931 if (!MatchQ)
932 MatchChars[NumMatches++] = 'q';
933
934 SmallString<126> Msg;
935 raw_svector_ostream OS(Msg);
936 OS << "ambiguous instructions require an explicit suffix (could be ";
937 for (unsigned i = 0; i != NumMatches; ++i) {
938 if (i != 0)
939 OS << ", ";
940 if (i + 1 == NumMatches)
941 OS << "or ";
942 OS << "'" << Base << MatchChars[i] << "'";
943 }
944 OS << ")";
945 Error(IDLoc, OS.str());
946 } else {
947 // FIXME: We should give nicer diagnostics about the exact failure.
948 Error(IDLoc, "unrecognized instruction");
949 }
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000950
Daniel Dunbarc918d602010-05-04 16:12:42 +0000951 return true;
952}
953
954
Sean Callanane88f5522010-01-23 02:43:15 +0000955extern "C" void LLVMInitializeX86AsmLexer();
956
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000957// Force static initialization.
958extern "C" void LLVMInitializeX86AsmParser() {
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000959 RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
960 RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
Sean Callanane88f5522010-01-23 02:43:15 +0000961 LLVMInitializeX86AsmLexer();
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000962}
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000963
964#include "X86GenAsmMatcher.inc"