blob: 7ba2f7cb82e38f3079feeb7a2763f2c3d20d110d [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
44 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
45
46 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
47
Chris Lattner29ef9a22010-01-15 18:51:29 +000048 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000049
Chris Lattner309264d2010-01-15 18:44:13 +000050 X86Operand *ParseOperand();
Chris Lattnereef6d782010-04-17 18:56:34 +000051 X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
Kevin Enderby9c656452009-09-10 20:51:44 +000052
53 bool ParseDirectiveWord(unsigned Size, SMLoc L);
54
Daniel Dunbarf1e29d42010-08-12 00:55:38 +000055 bool MatchInstruction(SMLoc IDLoc,
56 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbar20927f22009-08-07 08:26:05 +000057 MCInst &Inst);
58
Daniel Dunbar54074b52010-07-19 05:44:09 +000059 /// @name Auto-generated Matcher Functions
60 /// {
61
62 unsigned ComputeAvailableFeatures(const X86Subtarget *Subtarget) const;
63
Daniel Dunbarc918d602010-05-04 16:12:42 +000064 bool MatchInstructionImpl(
65 const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst);
66
Daniel Dunbar0e2771f2009-07-29 00:02:19 +000067 /// }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000068
69public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000070 X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
Daniel Dunbar54074b52010-07-19 05:44:09 +000071 : TargetAsmParser(T), Parser(_Parser), TM(TM) {
72
73 // Initialize the set of available features.
74 setAvailableFeatures(ComputeAvailableFeatures(
75 &TM.getSubtarget<X86Subtarget>()));
76 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000077
Benjamin Kramer38e59892010-07-14 22:38:02 +000078 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +000079 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderby9c656452009-09-10 20:51:44 +000080
81 virtual bool ParseDirective(AsmToken DirectiveID);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000082};
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +000083
Daniel Dunbarf98bc632010-03-18 20:06:02 +000084class X86_32ATTAsmParser : public X86ATTAsmParser {
85public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000086 X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
87 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbarf98bc632010-03-18 20:06:02 +000088 Is64Bit = false;
89 }
90};
91
92class X86_64ATTAsmParser : public X86ATTAsmParser {
93public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000094 X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
95 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbarf98bc632010-03-18 20:06:02 +000096 Is64Bit = true;
97 }
98};
99
Chris Lattner37dfdec2009-07-29 06:33:53 +0000100} // end anonymous namespace
101
Sean Callanane9b466d2010-01-23 00:40:33 +0000102/// @name Auto-generated Match Functions
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000103/// {
Sean Callanane9b466d2010-01-23 00:40:33 +0000104
Chris Lattnerb8d6e982010-02-09 00:34:28 +0000105static unsigned MatchRegisterName(StringRef Name);
Sean Callanane9b466d2010-01-23 00:40:33 +0000106
107/// }
Chris Lattner37dfdec2009-07-29 06:33:53 +0000108
109namespace {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000110
111/// X86Operand - Instances of this class represent a parsed X86 machine
112/// instruction.
Chris Lattner45220a82010-01-14 21:20:55 +0000113struct X86Operand : public MCParsedAsmOperand {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000114 enum KindTy {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000115 Token,
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000116 Register,
117 Immediate,
118 Memory
119 } Kind;
120
Chris Lattner29ef9a22010-01-15 18:51:29 +0000121 SMLoc StartLoc, EndLoc;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000122
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000123 union {
124 struct {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000125 const char *Data;
126 unsigned Length;
127 } Tok;
128
129 struct {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000130 unsigned RegNo;
131 } Reg;
132
133 struct {
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000134 const MCExpr *Val;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000135 } Imm;
136
137 struct {
138 unsigned SegReg;
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000139 const MCExpr *Disp;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000140 unsigned BaseReg;
141 unsigned IndexReg;
142 unsigned Scale;
143 } Mem;
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000144 };
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000145
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000146 X86Operand(KindTy K, SMLoc Start, SMLoc End)
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000147 : Kind(K), StartLoc(Start), EndLoc(End) {}
Daniel Dunbarc918d602010-05-04 16:12:42 +0000148
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000149 /// getStartLoc - Get the location of the first token of this operand.
150 SMLoc getStartLoc() const { return StartLoc; }
151 /// getEndLoc - Get the location of the last token of this operand.
152 SMLoc getEndLoc() const { return EndLoc; }
153
Daniel Dunbarb3cb6962010-08-11 06:37:04 +0000154 virtual void dump(raw_ostream &OS) const {}
155
Daniel Dunbar20927f22009-08-07 08:26:05 +0000156 StringRef getToken() const {
157 assert(Kind == Token && "Invalid access!");
158 return StringRef(Tok.Data, Tok.Length);
159 }
Daniel Dunbarc918d602010-05-04 16:12:42 +0000160 void setTokenValue(StringRef Value) {
161 assert(Kind == Token && "Invalid access!");
162 Tok.Data = Value.data();
163 Tok.Length = Value.size();
164 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000165
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000166 unsigned getReg() const {
167 assert(Kind == Register && "Invalid access!");
168 return Reg.RegNo;
169 }
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000170
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000171 const MCExpr *getImm() const {
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000172 assert(Kind == Immediate && "Invalid access!");
173 return Imm.Val;
174 }
175
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000176 const MCExpr *getMemDisp() const {
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000177 assert(Kind == Memory && "Invalid access!");
178 return Mem.Disp;
179 }
180 unsigned getMemSegReg() const {
181 assert(Kind == Memory && "Invalid access!");
182 return Mem.SegReg;
183 }
184 unsigned getMemBaseReg() const {
185 assert(Kind == Memory && "Invalid access!");
186 return Mem.BaseReg;
187 }
188 unsigned getMemIndexReg() const {
189 assert(Kind == Memory && "Invalid access!");
190 return Mem.IndexReg;
191 }
192 unsigned getMemScale() const {
193 assert(Kind == Memory && "Invalid access!");
194 return Mem.Scale;
195 }
196
Daniel Dunbara3741fa2009-08-08 07:50:56 +0000197 bool isToken() const {return Kind == Token; }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000198
199 bool isImm() const { return Kind == Immediate; }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000200
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000201 bool isImmSExti16i8() const {
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000202 if (!isImm())
203 return false;
204
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000205 // If this isn't a constant expr, just assume it fits and let relaxation
206 // handle it.
207 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
208 if (!CE)
209 return true;
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000210
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000211 // Otherwise, check the value is in a range that makes sense for this
212 // extension.
213 uint64_t Value = CE->getValue();
214 return (( Value <= 0x000000000000007FULL)||
215 (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)||
216 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000217 }
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000218 bool isImmSExti32i8() const {
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000219 if (!isImm())
220 return false;
221
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000222 // If this isn't a constant expr, just assume it fits and let relaxation
223 // handle it.
224 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
225 if (!CE)
226 return true;
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000227
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000228 // Otherwise, check the value is in a range that makes sense for this
229 // extension.
230 uint64_t Value = CE->getValue();
231 return (( Value <= 0x000000000000007FULL)||
232 (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
233 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
234 }
235 bool isImmSExti64i8() const {
236 if (!isImm())
237 return false;
238
239 // If this isn't a constant expr, just assume it fits and let relaxation
240 // handle it.
241 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
242 if (!CE)
243 return true;
244
245 // Otherwise, check the value is in a range that makes sense for this
246 // extension.
247 uint64_t Value = CE->getValue();
248 return (( Value <= 0x000000000000007FULL)||
249 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
250 }
251 bool isImmSExti64i32() const {
252 if (!isImm())
253 return false;
254
255 // If this isn't a constant expr, just assume it fits and let relaxation
256 // handle it.
257 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
258 if (!CE)
259 return true;
260
261 // Otherwise, check the value is in a range that makes sense for this
262 // extension.
263 uint64_t Value = CE->getValue();
264 return (( Value <= 0x000000007FFFFFFFULL)||
265 (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000266 }
267
Daniel Dunbar20927f22009-08-07 08:26:05 +0000268 bool isMem() const { return Kind == Memory; }
269
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000270 bool isAbsMem() const {
271 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000272 !getMemIndexReg() && getMemScale() == 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000273 }
274
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000275 bool isNoSegMem() const {
276 return Kind == Memory && !getMemSegReg();
277 }
278
Daniel Dunbar20927f22009-08-07 08:26:05 +0000279 bool isReg() const { return Kind == Register; }
280
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000281 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
282 // Add as immediates when possible.
283 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
284 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
285 else
286 Inst.addOperand(MCOperand::CreateExpr(Expr));
287 }
288
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000289 void addRegOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000290 assert(N == 1 && "Invalid number of operands!");
291 Inst.addOperand(MCOperand::CreateReg(getReg()));
292 }
293
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000294 void addImmOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000295 assert(N == 1 && "Invalid number of operands!");
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000296 addExpr(Inst, getImm());
Daniel Dunbar20927f22009-08-07 08:26:05 +0000297 }
298
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000299 void addMemOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000300 assert((N == 5) && "Invalid number of operands!");
Daniel Dunbar20927f22009-08-07 08:26:05 +0000301 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
302 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
303 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000304 addExpr(Inst, getMemDisp());
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000305 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
306 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000307
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000308 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
309 assert((N == 1) && "Invalid number of operands!");
310 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
311 }
312
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000313 void addNoSegMemOperands(MCInst &Inst, unsigned N) const {
314 assert((N == 4) && "Invalid number of operands!");
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000315 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
316 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
317 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000318 addExpr(Inst, getMemDisp());
Daniel Dunbar20927f22009-08-07 08:26:05 +0000319 }
320
Chris Lattnerb4307b32010-01-15 19:28:38 +0000321 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
322 X86Operand *Res = new X86Operand(Token, Loc, Loc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000323 Res->Tok.Data = Str.data();
324 Res->Tok.Length = Str.size();
Daniel Dunbar20927f22009-08-07 08:26:05 +0000325 return Res;
326 }
327
Chris Lattner29ef9a22010-01-15 18:51:29 +0000328 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000329 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000330 Res->Reg.RegNo = RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000331 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000332 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000333
Chris Lattnerb4307b32010-01-15 19:28:38 +0000334 static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
335 X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000336 Res->Imm.Val = Val;
337 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000338 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000339
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000340 /// Create an absolute memory operand.
341 static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
342 SMLoc EndLoc) {
343 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
344 Res->Mem.SegReg = 0;
345 Res->Mem.Disp = Disp;
346 Res->Mem.BaseReg = 0;
347 Res->Mem.IndexReg = 0;
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000348 Res->Mem.Scale = 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000349 return Res;
350 }
351
352 /// Create a generalized memory operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000353 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
354 unsigned BaseReg, unsigned IndexReg,
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000355 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000356 // We should never just have a displacement, that should be parsed as an
357 // absolute memory operand.
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000358 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
359
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000360 // The scale should always be one of {1,2,4,8}.
361 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000362 "Invalid scale!");
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000363 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000364 Res->Mem.SegReg = SegReg;
365 Res->Mem.Disp = Disp;
366 Res->Mem.BaseReg = BaseReg;
367 Res->Mem.IndexReg = IndexReg;
368 Res->Mem.Scale = Scale;
369 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000370 }
371};
Daniel Dunbara3af3702009-07-20 18:55:04 +0000372
Chris Lattner37dfdec2009-07-29 06:33:53 +0000373} // end anonymous namespace.
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000374
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000375
Chris Lattner29ef9a22010-01-15 18:51:29 +0000376bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
377 SMLoc &StartLoc, SMLoc &EndLoc) {
Chris Lattner23075742010-01-15 18:27:19 +0000378 RegNo = 0;
Sean Callanan18b83232010-01-19 21:44:56 +0000379 const AsmToken &TokPercent = Parser.getTok();
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000380 assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
Chris Lattner29ef9a22010-01-15 18:51:29 +0000381 StartLoc = TokPercent.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000382 Parser.Lex(); // Eat percent token.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000383
Sean Callanan18b83232010-01-19 21:44:56 +0000384 const AsmToken &Tok = Parser.getTok();
Kevin Enderby0d6cd002009-09-16 17:18:29 +0000385 if (Tok.isNot(AsmToken::Identifier))
386 return Error(Tok.getLoc(), "invalid register name");
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000387
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000388 // FIXME: Validate register for the current architecture; we have to do
389 // validation later, so maybe there is no need for this here.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000390 RegNo = MatchRegisterName(Tok.getString());
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000391
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000392 // FIXME: This should be done using Requires<In32BitMode> and
393 // Requires<In64BitMode> so "eiz" usage in 64-bit instructions
394 // can be also checked.
395 if (RegNo == X86::RIZ && !Is64Bit)
396 return Error(Tok.getLoc(), "riz register in 64-bit mode only");
397
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000398 // Parse %st(1) and "%st" as "%st(0)"
399 if (RegNo == 0 && Tok.getString() == "st") {
400 RegNo = X86::ST0;
401 EndLoc = Tok.getLoc();
402 Parser.Lex(); // Eat 'st'
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000403
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000404 // Check to see if we have '(4)' after %st.
405 if (getLexer().isNot(AsmToken::LParen))
406 return false;
407 // Lex the paren.
408 getParser().Lex();
409
410 const AsmToken &IntTok = Parser.getTok();
411 if (IntTok.isNot(AsmToken::Integer))
412 return Error(IntTok.getLoc(), "expected stack index");
413 switch (IntTok.getIntVal()) {
414 case 0: RegNo = X86::ST0; break;
415 case 1: RegNo = X86::ST1; break;
416 case 2: RegNo = X86::ST2; break;
417 case 3: RegNo = X86::ST3; break;
418 case 4: RegNo = X86::ST4; break;
419 case 5: RegNo = X86::ST5; break;
420 case 6: RegNo = X86::ST6; break;
421 case 7: RegNo = X86::ST7; break;
422 default: return Error(IntTok.getLoc(), "invalid stack index");
423 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000424
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000425 if (getParser().Lex().isNot(AsmToken::RParen))
426 return Error(Parser.getTok().getLoc(), "expected ')'");
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000427
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000428 EndLoc = Tok.getLoc();
429 Parser.Lex(); // Eat ')'
430 return false;
431 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000432
Chris Lattner645b2092010-06-24 07:29:18 +0000433 // If this is "db[0-7]", match it as an alias
434 // for dr[0-7].
435 if (RegNo == 0 && Tok.getString().size() == 3 &&
436 Tok.getString().startswith("db")) {
437 switch (Tok.getString()[2]) {
438 case '0': RegNo = X86::DR0; break;
439 case '1': RegNo = X86::DR1; break;
440 case '2': RegNo = X86::DR2; break;
441 case '3': RegNo = X86::DR3; break;
442 case '4': RegNo = X86::DR4; break;
443 case '5': RegNo = X86::DR5; break;
444 case '6': RegNo = X86::DR6; break;
445 case '7': RegNo = X86::DR7; break;
446 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000447
Chris Lattner645b2092010-06-24 07:29:18 +0000448 if (RegNo != 0) {
449 EndLoc = Tok.getLoc();
450 Parser.Lex(); // Eat it.
451 return false;
452 }
453 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000454
Daniel Dunbar245f0582009-08-08 21:22:41 +0000455 if (RegNo == 0)
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000456 return Error(Tok.getLoc(), "invalid register name");
457
Chris Lattner29ef9a22010-01-15 18:51:29 +0000458 EndLoc = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000459 Parser.Lex(); // Eat identifier token.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000460 return false;
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000461}
462
Chris Lattner309264d2010-01-15 18:44:13 +0000463X86Operand *X86ATTAsmParser::ParseOperand() {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000464 switch (getLexer().getKind()) {
465 default:
Chris Lattnereef6d782010-04-17 18:56:34 +0000466 // Parse a memory operand with no segment register.
467 return ParseMemOperand(0, Parser.getTok().getLoc());
Chris Lattner23075742010-01-15 18:27:19 +0000468 case AsmToken::Percent: {
Chris Lattnereef6d782010-04-17 18:56:34 +0000469 // Read the register.
Chris Lattner23075742010-01-15 18:27:19 +0000470 unsigned RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000471 SMLoc Start, End;
472 if (ParseRegister(RegNo, Start, End)) return 0;
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000473 if (RegNo == X86::EIZ || RegNo == X86::RIZ) {
474 Error(Start, "eiz and riz can only be used as index registers");
475 return 0;
476 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000477
Chris Lattnereef6d782010-04-17 18:56:34 +0000478 // If this is a segment register followed by a ':', then this is the start
479 // of a memory reference, otherwise this is a normal register reference.
480 if (getLexer().isNot(AsmToken::Colon))
481 return X86Operand::CreateReg(RegNo, Start, End);
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000482
483
Chris Lattnereef6d782010-04-17 18:56:34 +0000484 getParser().Lex(); // Eat the colon.
485 return ParseMemOperand(RegNo, Start);
Chris Lattner23075742010-01-15 18:27:19 +0000486 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000487 case AsmToken::Dollar: {
488 // $42 -> immediate.
Sean Callanan18b83232010-01-19 21:44:56 +0000489 SMLoc Start = Parser.getTok().getLoc(), End;
Sean Callananb9a25b72010-01-19 20:27:46 +0000490 Parser.Lex();
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000491 const MCExpr *Val;
Chris Lattner54482b42010-01-15 19:39:23 +0000492 if (getParser().ParseExpression(Val, End))
Chris Lattner309264d2010-01-15 18:44:13 +0000493 return 0;
Chris Lattnerb4307b32010-01-15 19:28:38 +0000494 return X86Operand::CreateImm(Val, Start, End);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000495 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000496 }
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000497}
498
Chris Lattnereef6d782010-04-17 18:56:34 +0000499/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
500/// has already been parsed if present.
501X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000502
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000503 // We have to disambiguate a parenthesized expression "(4+5)" from the start
504 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
Chris Lattner75f265f2010-01-24 01:07:33 +0000505 // only way to do this without lookahead is to eat the '(' and see what is
506 // after it.
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000507 const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000508 if (getLexer().isNot(AsmToken::LParen)) {
Chris Lattner54482b42010-01-15 19:39:23 +0000509 SMLoc ExprEnd;
510 if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000511
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000512 // After parsing the base expression we could either have a parenthesized
513 // memory address or not. If not, return now. If so, eat the (.
514 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000515 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000516 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000517 return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000518 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000519 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000520
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000521 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000522 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000523 } else {
524 // Okay, we have a '('. We don't know if this is an expression or not, but
525 // so we have to eat the ( to see beyond it.
Sean Callanan18b83232010-01-19 21:44:56 +0000526 SMLoc LParenLoc = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000527 Parser.Lex(); // Eat the '('.
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000528
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000529 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000530 // Nothing to do here, fall into the code below with the '(' part of the
531 // memory operand consumed.
532 } else {
Chris Lattnerb4307b32010-01-15 19:28:38 +0000533 SMLoc ExprEnd;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000534
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000535 // It must be an parenthesized expression, parse it now.
Chris Lattnerb4307b32010-01-15 19:28:38 +0000536 if (getParser().ParseParenExpression(Disp, ExprEnd))
Chris Lattner309264d2010-01-15 18:44:13 +0000537 return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000538
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000539 // After parsing the base expression we could either have a parenthesized
540 // memory address or not. If not, return now. If so, eat the (.
541 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000542 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000543 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000544 return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000545 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000546 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000547
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000548 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000549 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000550 }
551 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000552
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000553 // If we reached here, then we just ate the ( of the memory operand. Process
554 // the rest of the memory operand.
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000555 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000556
Chris Lattner29ef9a22010-01-15 18:51:29 +0000557 if (getLexer().is(AsmToken::Percent)) {
558 SMLoc L;
559 if (ParseRegister(BaseReg, L, L)) return 0;
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000560 if (BaseReg == X86::EIZ || BaseReg == X86::RIZ) {
561 Error(L, "eiz and riz can only be used as index registers");
562 return 0;
563 }
Chris Lattner29ef9a22010-01-15 18:51:29 +0000564 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000565
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000566 if (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000567 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000568
569 // Following the comma we should have either an index register, or a scale
570 // value. We don't support the later form, but we want to parse it
571 // correctly.
572 //
573 // Not that even though it would be completely consistent to support syntax
Bruno Cardoso Lopes3c8e1be2010-07-24 00:06:39 +0000574 // like "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000575 if (getLexer().is(AsmToken::Percent)) {
Chris Lattner29ef9a22010-01-15 18:51:29 +0000576 SMLoc L;
577 if (ParseRegister(IndexReg, L, L)) return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000578
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000579 if (getLexer().isNot(AsmToken::RParen)) {
580 // Parse the scale amount:
581 // ::= ',' [scale-expression]
Chris Lattner309264d2010-01-15 18:44:13 +0000582 if (getLexer().isNot(AsmToken::Comma)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000583 Error(Parser.getTok().getLoc(),
Chris Lattner309264d2010-01-15 18:44:13 +0000584 "expected comma in scale expression");
585 return 0;
586 }
Sean Callananb9a25b72010-01-19 20:27:46 +0000587 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000588
589 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000590 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000591
592 int64_t ScaleVal;
593 if (getParser().ParseAbsoluteExpression(ScaleVal))
Chris Lattner309264d2010-01-15 18:44:13 +0000594 return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000595
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000596 // Validate the scale amount.
Chris Lattner309264d2010-01-15 18:44:13 +0000597 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
598 Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
599 return 0;
600 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000601 Scale = (unsigned)ScaleVal;
602 }
603 }
604 } else if (getLexer().isNot(AsmToken::RParen)) {
605 // Otherwise we have the unsupported form of a scale amount without an
606 // index.
Sean Callanan18b83232010-01-19 21:44:56 +0000607 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000608
609 int64_t Value;
610 if (getParser().ParseAbsoluteExpression(Value))
Chris Lattner309264d2010-01-15 18:44:13 +0000611 return 0;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000612
Chris Lattner309264d2010-01-15 18:44:13 +0000613 Error(Loc, "cannot have scale factor without index register");
614 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000615 }
616 }
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000617
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000618 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
Chris Lattner309264d2010-01-15 18:44:13 +0000619 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000620 Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
Chris Lattner309264d2010-01-15 18:44:13 +0000621 return 0;
622 }
Sean Callanan18b83232010-01-19 21:44:56 +0000623 SMLoc MemEnd = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000624 Parser.Lex(); // Eat the ')'.
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000625
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000626 return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
627 MemStart, MemEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000628}
629
Chris Lattner98986712010-01-14 22:21:20 +0000630bool X86ATTAsmParser::
Benjamin Kramer38e59892010-07-14 22:38:02 +0000631ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000632 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000633 // The various flavors of pushf and popf use Requires<In32BitMode> and
634 // Requires<In64BitMode>, but the assembler doesn't yet implement that.
635 // For now, just do a manual check to prevent silent misencoding.
636 if (Is64Bit) {
637 if (Name == "popfl")
638 return Error(NameLoc, "popfl cannot be encoded in 64-bit mode");
639 else if (Name == "pushfl")
640 return Error(NameLoc, "pushfl cannot be encoded in 64-bit mode");
Kevin Enderby52a18ae2010-07-13 20:05:41 +0000641 else if (Name == "pusha")
642 return Error(NameLoc, "pusha cannot be encoded in 64-bit mode");
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000643 } else {
644 if (Name == "popfq")
645 return Error(NameLoc, "popfq cannot be encoded in 32-bit mode");
646 else if (Name == "pushfq")
647 return Error(NameLoc, "pushfq cannot be encoded in 32-bit mode");
648 }
649
Kevin Enderby09712b52010-06-08 23:48:44 +0000650 // The "Jump if rCX Zero" form jcxz is not allowed in 64-bit mode and
651 // the form jrcxz is not allowed in 32-bit mode.
652 if (Is64Bit) {
653 if (Name == "jcxz")
654 return Error(NameLoc, "jcxz cannot be encoded in 64-bit mode");
655 } else {
656 if (Name == "jrcxz")
657 return Error(NameLoc, "jrcxz cannot be encoded in 32-bit mode");
658 }
659
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000660 // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
661 // represent alternative syntaxes in the .td file, without requiring
662 // instruction duplication.
663 StringRef PatchedName = StringSwitch<StringRef>(Name)
664 .Case("sal", "shl")
665 .Case("salb", "shlb")
666 .Case("sall", "shll")
667 .Case("salq", "shlq")
668 .Case("salw", "shlw")
669 .Case("repe", "rep")
670 .Case("repz", "rep")
671 .Case("repnz", "repne")
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000672 .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
673 .Case("popf", Is64Bit ? "popfq" : "popfl")
Kevin Enderby9d31d792010-05-21 23:01:38 +0000674 .Case("retl", Is64Bit ? "retl" : "ret")
675 .Case("retq", Is64Bit ? "ret" : "retq")
Daniel Dunbar4c361972010-05-22 06:37:33 +0000676 .Case("setz", "sete")
677 .Case("setnz", "setne")
678 .Case("jz", "je")
679 .Case("jnz", "jne")
Kevin Enderbybd658912010-05-27 21:33:19 +0000680 .Case("jc", "jb")
Kevin Enderby09712b52010-06-08 23:48:44 +0000681 // FIXME: in 32-bit mode jcxz requires an AdSize prefix. In 64-bit mode
682 // jecxz requires an AdSize prefix but jecxz does not have a prefix in
683 // 32-bit mode.
Kevin Enderbybd658912010-05-27 21:33:19 +0000684 .Case("jecxz", "jcxz")
Kevin Enderby09712b52010-06-08 23:48:44 +0000685 .Case("jrcxz", "jcxz")
Kevin Enderbybd658912010-05-27 21:33:19 +0000686 .Case("jna", "jbe")
687 .Case("jnae", "jb")
688 .Case("jnb", "jae")
689 .Case("jnbe", "ja")
690 .Case("jnc", "jae")
691 .Case("jng", "jle")
692 .Case("jnge", "jl")
693 .Case("jnl", "jge")
694 .Case("jnle", "jg")
695 .Case("jpe", "jp")
696 .Case("jpo", "jnp")
Kevin Enderbyca956dc2010-05-24 20:32:23 +0000697 .Case("cmovcl", "cmovbl")
698 .Case("cmovcl", "cmovbl")
699 .Case("cmovnal", "cmovbel")
700 .Case("cmovnbl", "cmovael")
701 .Case("cmovnbel", "cmoval")
702 .Case("cmovncl", "cmovael")
703 .Case("cmovngl", "cmovlel")
704 .Case("cmovnl", "cmovgel")
705 .Case("cmovngl", "cmovlel")
706 .Case("cmovngel", "cmovll")
707 .Case("cmovnll", "cmovgel")
708 .Case("cmovnlel", "cmovgl")
709 .Case("cmovnzl", "cmovnel")
710 .Case("cmovzl", "cmovel")
Kevin Enderby5e394422010-05-28 20:59:10 +0000711 .Case("fwait", "wait")
Kevin Enderby31cc9652010-05-28 21:20:21 +0000712 .Case("movzx", "movzb")
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000713 .Default(Name);
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000714
715 // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
716 const MCExpr *ExtraImmOp = 0;
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000717 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000718 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
719 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000720 bool IsVCMP = PatchedName.startswith("vcmp");
721 unsigned SSECCIdx = IsVCMP ? 4 : 3;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000722 unsigned SSEComparisonCode = StringSwitch<unsigned>(
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000723 PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
Bruno Cardoso Lopescc69e132010-07-07 22:24:03 +0000724 .Case("eq", 0)
725 .Case("lt", 1)
726 .Case("le", 2)
727 .Case("unord", 3)
728 .Case("neq", 4)
729 .Case("nlt", 5)
730 .Case("nle", 6)
731 .Case("ord", 7)
732 .Case("eq_uq", 8)
733 .Case("nge", 9)
734 .Case("ngt", 0x0A)
735 .Case("false", 0x0B)
736 .Case("neq_oq", 0x0C)
737 .Case("ge", 0x0D)
738 .Case("gt", 0x0E)
739 .Case("true", 0x0F)
740 .Case("eq_os", 0x10)
741 .Case("lt_oq", 0x11)
742 .Case("le_oq", 0x12)
743 .Case("unord_s", 0x13)
744 .Case("neq_us", 0x14)
745 .Case("nlt_uq", 0x15)
746 .Case("nle_uq", 0x16)
747 .Case("ord_s", 0x17)
748 .Case("eq_us", 0x18)
749 .Case("nge_uq", 0x19)
750 .Case("ngt_uq", 0x1A)
751 .Case("false_os", 0x1B)
752 .Case("neq_os", 0x1C)
753 .Case("ge_oq", 0x1D)
754 .Case("gt_oq", 0x1E)
755 .Case("true_us", 0x1F)
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000756 .Default(~0U);
757 if (SSEComparisonCode != ~0U) {
758 ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode,
759 getParser().getContext());
760 if (PatchedName.endswith("ss")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000761 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000762 } else if (PatchedName.endswith("sd")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000763 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000764 } else if (PatchedName.endswith("ps")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000765 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000766 } else {
767 assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000768 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000769 }
770 }
771 }
Bruno Cardoso Lopesf528d2b2010-07-23 18:41:12 +0000772
773 // FIXME: Hack to recognize vpclmul<src1_quadword, src2_quadword>dq
774 if (PatchedName.startswith("vpclmul")) {
775 unsigned CLMULQuadWordSelect = StringSwitch<unsigned>(
776 PatchedName.slice(7, PatchedName.size() - 2))
777 .Case("lqlq", 0x00) // src1[63:0], src2[63:0]
778 .Case("hqlq", 0x01) // src1[127:64], src2[63:0]
779 .Case("lqhq", 0x10) // src1[63:0], src2[127:64]
780 .Case("hqhq", 0x11) // src1[127:64], src2[127:64]
781 .Default(~0U);
782 if (CLMULQuadWordSelect != ~0U) {
783 ExtraImmOp = MCConstantExpr::Create(CLMULQuadWordSelect,
784 getParser().getContext());
785 assert(PatchedName.endswith("dq") && "Unexpected mnemonic!");
786 PatchedName = "vpclmulqdq";
787 }
788 }
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000789 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000790
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000791 if (ExtraImmOp)
792 Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
793
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000794 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000795
796 // Parse '*' modifier.
797 if (getLexer().is(AsmToken::Star)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000798 SMLoc Loc = Parser.getTok().getLoc();
Chris Lattnerb4307b32010-01-15 19:28:38 +0000799 Operands.push_back(X86Operand::CreateToken("*", Loc));
Sean Callananb9a25b72010-01-19 20:27:46 +0000800 Parser.Lex(); // Eat the star.
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000801 }
802
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000803 // Read the first operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000804 if (X86Operand *Op = ParseOperand())
805 Operands.push_back(Op);
806 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000807 return true;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000808
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000809 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000810 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000811
812 // Parse and remember the operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000813 if (X86Operand *Op = ParseOperand())
814 Operands.push_back(Op);
815 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000816 return true;
817 }
818 }
819
Daniel Dunbard5e77052010-03-13 00:47:29 +0000820 // FIXME: Hack to handle recognizing s{hr,ar,hl}? $1.
821 if ((Name.startswith("shr") || Name.startswith("sar") ||
822 Name.startswith("shl")) &&
823 Operands.size() == 3 &&
824 static_cast<X86Operand*>(Operands[1])->isImm() &&
825 isa<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm()) &&
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000826 cast<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm())->getValue() == 1) {
827 delete Operands[1];
Daniel Dunbard5e77052010-03-13 00:47:29 +0000828 Operands.erase(Operands.begin() + 1);
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000829 }
Daniel Dunbard5e77052010-03-13 00:47:29 +0000830
Kevin Enderbycf50a532010-05-25 20:52:34 +0000831 // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
832 // "f{mul*,add*,sub*,div*} $op"
833 if ((Name.startswith("fmul") || Name.startswith("fadd") ||
834 Name.startswith("fsub") || Name.startswith("fdiv")) &&
835 Operands.size() == 3 &&
836 static_cast<X86Operand*>(Operands[2])->isReg() &&
837 static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
838 delete Operands[2];
839 Operands.erase(Operands.begin() + 2);
840 }
841
Chris Lattner98986712010-01-14 22:21:20 +0000842 return false;
Daniel Dunbara3af3702009-07-20 18:55:04 +0000843}
844
Kevin Enderby9c656452009-09-10 20:51:44 +0000845bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
846 StringRef IDVal = DirectiveID.getIdentifier();
847 if (IDVal == ".word")
848 return ParseDirectiveWord(2, DirectiveID.getLoc());
849 return true;
850}
851
852/// ParseDirectiveWord
853/// ::= .word [ expression (, expression)* ]
854bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
855 if (getLexer().isNot(AsmToken::EndOfStatement)) {
856 for (;;) {
857 const MCExpr *Value;
858 if (getParser().ParseExpression(Value))
859 return true;
860
Chris Lattneraaec2052010-01-19 19:46:13 +0000861 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
Kevin Enderby9c656452009-09-10 20:51:44 +0000862
863 if (getLexer().is(AsmToken::EndOfStatement))
864 break;
Bruno Cardoso Lopesf64a7d42010-07-23 22:15:26 +0000865
Kevin Enderby9c656452009-09-10 20:51:44 +0000866 // FIXME: Improve diagnostic.
867 if (getLexer().isNot(AsmToken::Comma))
868 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000869 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000870 }
871 }
872
Sean Callananb9a25b72010-01-19 20:27:46 +0000873 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000874 return false;
875}
876
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000877
Daniel Dunbarc918d602010-05-04 16:12:42 +0000878bool
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000879X86ATTAsmParser::MatchInstruction(SMLoc IDLoc,
880 const SmallVectorImpl<MCParsedAsmOperand*>
Daniel Dunbarc918d602010-05-04 16:12:42 +0000881 &Operands,
882 MCInst &Inst) {
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000883 assert(!Operands.empty() && "Unexpect empty operand list!");
884
885 X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
886 assert(Op->isToken() && "Leading operand should always be a mnemonic!");
887
Daniel Dunbarc918d602010-05-04 16:12:42 +0000888 // First, try a direct match.
889 if (!MatchInstructionImpl(Operands, Inst))
890 return false;
891
Daniel Dunbarc918d602010-05-04 16:12:42 +0000892 // FIXME: Ideally, we would only attempt suffix matches for things which are
893 // valid prefixes, and we could just infer the right unambiguous
894 // type. However, that requires substantially more matcher support than the
895 // following hack.
896
897 // Change the operand to point to a temporary token.
Daniel Dunbarc918d602010-05-04 16:12:42 +0000898 StringRef Base = Op->getToken();
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000899 SmallString<16> Tmp;
900 Tmp += Base;
901 Tmp += ' ';
902 Op->setTokenValue(Tmp.str());
Daniel Dunbarc918d602010-05-04 16:12:42 +0000903
904 // Check for the various suffix matches.
905 Tmp[Base.size()] = 'b';
906 bool MatchB = MatchInstructionImpl(Operands, Inst);
907 Tmp[Base.size()] = 'w';
908 bool MatchW = MatchInstructionImpl(Operands, Inst);
909 Tmp[Base.size()] = 'l';
910 bool MatchL = MatchInstructionImpl(Operands, Inst);
Daniel Dunbar04814492010-05-12 00:54:20 +0000911 Tmp[Base.size()] = 'q';
912 bool MatchQ = MatchInstructionImpl(Operands, Inst);
Daniel Dunbarc918d602010-05-04 16:12:42 +0000913
914 // Restore the old token.
915 Op->setTokenValue(Base);
916
917 // If exactly one matched, then we treat that as a successful match (and the
918 // instruction will already have been filled in correctly, since the failing
919 // matches won't have modified it).
Daniel Dunbar04814492010-05-12 00:54:20 +0000920 if (MatchB + MatchW + MatchL + MatchQ == 3)
Daniel Dunbarc918d602010-05-04 16:12:42 +0000921 return false;
922
Daniel Dunbarc918d602010-05-04 16:12:42 +0000923 // Otherwise, the match failed.
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000924
Daniel Dunbar09062b12010-08-12 00:55:42 +0000925 // If we had multiple suffix matches, then identify this as an ambiguous
926 // match.
927 if (MatchB + MatchW + MatchL + MatchQ != 4) {
928 char MatchChars[4];
929 unsigned NumMatches = 0;
930 if (!MatchB)
931 MatchChars[NumMatches++] = 'b';
932 if (!MatchW)
933 MatchChars[NumMatches++] = 'w';
934 if (!MatchL)
935 MatchChars[NumMatches++] = 'l';
936 if (!MatchQ)
937 MatchChars[NumMatches++] = 'q';
938
939 SmallString<126> Msg;
940 raw_svector_ostream OS(Msg);
941 OS << "ambiguous instructions require an explicit suffix (could be ";
942 for (unsigned i = 0; i != NumMatches; ++i) {
943 if (i != 0)
944 OS << ", ";
945 if (i + 1 == NumMatches)
946 OS << "or ";
947 OS << "'" << Base << MatchChars[i] << "'";
948 }
949 OS << ")";
950 Error(IDLoc, OS.str());
951 } else {
952 // FIXME: We should give nicer diagnostics about the exact failure.
953 Error(IDLoc, "unrecognized instruction");
954 }
Daniel Dunbarf1e29d42010-08-12 00:55:38 +0000955
Daniel Dunbarc918d602010-05-04 16:12:42 +0000956 return true;
957}
958
959
Sean Callanane88f5522010-01-23 02:43:15 +0000960extern "C" void LLVMInitializeX86AsmLexer();
961
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000962// Force static initialization.
963extern "C" void LLVMInitializeX86AsmParser() {
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000964 RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
965 RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
Sean Callanane88f5522010-01-23 02:43:15 +0000966 LLVMInitializeX86AsmLexer();
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000967}
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000968
969#include "X86GenAsmMatcher.inc"