blob: 9e219baa2939aa6159b3720a83ab6776adb1a9a6 [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 Dunbardbd692a2009-07-20 20:01:54 +000012#include "llvm/ADT/SmallVector.h"
Daniel Dunbar1b6c0602010-02-10 21:19:28 +000013#include "llvm/ADT/StringSwitch.h"
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000014#include "llvm/ADT/Twine.h"
Kevin Enderby9c656452009-09-10 20:51:44 +000015#include "llvm/MC/MCStreamer.h"
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +000016#include "llvm/MC/MCExpr.h"
Daniel Dunbara027d222009-07-31 02:32:59 +000017#include "llvm/MC/MCInst.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000018#include "llvm/MC/MCParser/MCAsmLexer.h"
19#include "llvm/MC/MCParser/MCAsmParser.h"
20#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000021#include "llvm/Support/SourceMgr.h"
Daniel Dunbar092a9dd2009-07-17 20:42:00 +000022#include "llvm/Target/TargetRegistry.h"
23#include "llvm/Target/TargetAsmParser.h"
24using namespace llvm;
25
26namespace {
Benjamin Kramerc6b79ac2009-07-31 11:35:26 +000027struct X86Operand;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000028
29class X86ATTAsmParser : public TargetAsmParser {
30 MCAsmParser &Parser;
31
Daniel Dunbarf98bc632010-03-18 20:06:02 +000032protected:
33 unsigned Is64Bit : 1;
34
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000035private:
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000036 MCAsmParser &getParser() const { return Parser; }
37
38 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
39
40 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
41
42 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
43
Chris Lattner29ef9a22010-01-15 18:51:29 +000044 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000045
Chris Lattner309264d2010-01-15 18:44:13 +000046 X86Operand *ParseOperand();
Chris Lattnereef6d782010-04-17 18:56:34 +000047 X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
Kevin Enderby9c656452009-09-10 20:51:44 +000048
49 bool ParseDirectiveWord(unsigned Size, SMLoc L);
50
Daniel Dunbarf98bc632010-03-18 20:06:02 +000051 void InstructionCleanup(MCInst &Inst);
52
Daniel Dunbar0e2771f2009-07-29 00:02:19 +000053 /// @name Auto-generated Match Functions
Daniel Dunbarc918d602010-05-04 16:12:42 +000054 /// {
Daniel Dunbar0e2771f2009-07-29 00:02:19 +000055
Chris Lattner98986712010-01-14 22:21:20 +000056 bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbar20927f22009-08-07 08:26:05 +000057 MCInst &Inst);
58
Daniel Dunbarc918d602010-05-04 16:12:42 +000059 bool MatchInstructionImpl(
60 const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst);
61
Daniel Dunbar0e2771f2009-07-29 00:02:19 +000062 /// }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000063
64public:
65 X86ATTAsmParser(const Target &T, MCAsmParser &_Parser)
66 : TargetAsmParser(T), Parser(_Parser) {}
67
Chris Lattnerf007e852010-01-14 21:32:45 +000068 virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +000069 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderby9c656452009-09-10 20:51:44 +000070
71 virtual bool ParseDirective(AsmToken DirectiveID);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000072};
Daniel Dunbarf98bc632010-03-18 20:06:02 +000073
74class X86_32ATTAsmParser : public X86ATTAsmParser {
75public:
76 X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser)
77 : X86ATTAsmParser(T, _Parser) {
78 Is64Bit = false;
79 }
80};
81
82class X86_64ATTAsmParser : public X86ATTAsmParser {
83public:
84 X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser)
85 : X86ATTAsmParser(T, _Parser) {
86 Is64Bit = true;
87 }
88};
89
Chris Lattner37dfdec2009-07-29 06:33:53 +000090} // end anonymous namespace
91
Sean Callanane9b466d2010-01-23 00:40:33 +000092/// @name Auto-generated Match Functions
93/// {
94
Chris Lattnerb8d6e982010-02-09 00:34:28 +000095static unsigned MatchRegisterName(StringRef Name);
Sean Callanane9b466d2010-01-23 00:40:33 +000096
97/// }
Chris Lattner37dfdec2009-07-29 06:33:53 +000098
99namespace {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000100
101/// X86Operand - Instances of this class represent a parsed X86 machine
102/// instruction.
Chris Lattner45220a82010-01-14 21:20:55 +0000103struct X86Operand : public MCParsedAsmOperand {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000104 enum KindTy {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000105 Token,
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000106 Register,
107 Immediate,
108 Memory
109 } Kind;
110
Chris Lattner29ef9a22010-01-15 18:51:29 +0000111 SMLoc StartLoc, EndLoc;
112
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000113 union {
114 struct {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000115 const char *Data;
116 unsigned Length;
117 } Tok;
118
119 struct {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000120 unsigned RegNo;
121 } Reg;
122
123 struct {
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000124 const MCExpr *Val;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000125 } Imm;
126
127 struct {
128 unsigned SegReg;
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000129 const MCExpr *Disp;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000130 unsigned BaseReg;
131 unsigned IndexReg;
132 unsigned Scale;
133 } Mem;
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000134 };
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000135
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000136 X86Operand(KindTy K, SMLoc Start, SMLoc End)
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000137 : Kind(K), StartLoc(Start), EndLoc(End) {}
Daniel Dunbarc918d602010-05-04 16:12:42 +0000138
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000139 /// getStartLoc - Get the location of the first token of this operand.
140 SMLoc getStartLoc() const { return StartLoc; }
141 /// getEndLoc - Get the location of the last token of this operand.
142 SMLoc getEndLoc() const { return EndLoc; }
143
Daniel Dunbar20927f22009-08-07 08:26:05 +0000144 StringRef getToken() const {
145 assert(Kind == Token && "Invalid access!");
146 return StringRef(Tok.Data, Tok.Length);
147 }
Daniel Dunbarc918d602010-05-04 16:12:42 +0000148 void setTokenValue(StringRef Value) {
149 assert(Kind == Token && "Invalid access!");
150 Tok.Data = Value.data();
151 Tok.Length = Value.size();
152 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000153
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000154 unsigned getReg() const {
155 assert(Kind == Register && "Invalid access!");
156 return Reg.RegNo;
157 }
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000158
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000159 const MCExpr *getImm() const {
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000160 assert(Kind == Immediate && "Invalid access!");
161 return Imm.Val;
162 }
163
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000164 const MCExpr *getMemDisp() const {
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000165 assert(Kind == Memory && "Invalid access!");
166 return Mem.Disp;
167 }
168 unsigned getMemSegReg() const {
169 assert(Kind == Memory && "Invalid access!");
170 return Mem.SegReg;
171 }
172 unsigned getMemBaseReg() const {
173 assert(Kind == Memory && "Invalid access!");
174 return Mem.BaseReg;
175 }
176 unsigned getMemIndexReg() const {
177 assert(Kind == Memory && "Invalid access!");
178 return Mem.IndexReg;
179 }
180 unsigned getMemScale() const {
181 assert(Kind == Memory && "Invalid access!");
182 return Mem.Scale;
183 }
184
Daniel Dunbara3741fa2009-08-08 07:50:56 +0000185 bool isToken() const {return Kind == Token; }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000186
187 bool isImm() const { return Kind == Immediate; }
188
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000189 bool isImmSExti16i8() const {
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000190 if (!isImm())
191 return false;
192
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000193 // If this isn't a constant expr, just assume it fits and let relaxation
194 // handle it.
195 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
196 if (!CE)
197 return true;
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000198
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000199 // Otherwise, check the value is in a range that makes sense for this
200 // extension.
201 uint64_t Value = CE->getValue();
202 return (( Value <= 0x000000000000007FULL)||
203 (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)||
204 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000205 }
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000206 bool isImmSExti32i8() const {
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000207 if (!isImm())
208 return false;
209
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000210 // If this isn't a constant expr, just assume it fits and let relaxation
211 // handle it.
212 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
213 if (!CE)
214 return true;
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000215
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000216 // Otherwise, check the value is in a range that makes sense for this
217 // extension.
218 uint64_t Value = CE->getValue();
219 return (( Value <= 0x000000000000007FULL)||
220 (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
221 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
222 }
223 bool isImmSExti64i8() const {
224 if (!isImm())
225 return false;
226
227 // If this isn't a constant expr, just assume it fits and let relaxation
228 // handle it.
229 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
230 if (!CE)
231 return true;
232
233 // Otherwise, check the value is in a range that makes sense for this
234 // extension.
235 uint64_t Value = CE->getValue();
236 return (( Value <= 0x000000000000007FULL)||
237 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
238 }
239 bool isImmSExti64i32() const {
240 if (!isImm())
241 return false;
242
243 // If this isn't a constant expr, just assume it fits and let relaxation
244 // handle it.
245 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
246 if (!CE)
247 return true;
248
249 // Otherwise, check the value is in a range that makes sense for this
250 // extension.
251 uint64_t Value = CE->getValue();
252 return (( Value <= 0x000000007FFFFFFFULL)||
253 (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000254 }
255
Daniel Dunbar20927f22009-08-07 08:26:05 +0000256 bool isMem() const { return Kind == Memory; }
257
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000258 bool isAbsMem() const {
259 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000260 !getMemIndexReg() && getMemScale() == 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000261 }
262
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000263 bool isNoSegMem() const {
264 return Kind == Memory && !getMemSegReg();
265 }
266
Daniel Dunbar20927f22009-08-07 08:26:05 +0000267 bool isReg() const { return Kind == Register; }
268
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000269 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
270 // Add as immediates when possible.
271 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
272 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
273 else
274 Inst.addOperand(MCOperand::CreateExpr(Expr));
275 }
276
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000277 void addRegOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000278 assert(N == 1 && "Invalid number of operands!");
279 Inst.addOperand(MCOperand::CreateReg(getReg()));
280 }
281
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000282 void addImmOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000283 assert(N == 1 && "Invalid number of operands!");
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000284 addExpr(Inst, getImm());
Daniel Dunbar20927f22009-08-07 08:26:05 +0000285 }
286
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000287 void addMemOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000288 assert((N == 5) && "Invalid number of operands!");
Daniel Dunbar20927f22009-08-07 08:26:05 +0000289 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
290 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
291 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000292 addExpr(Inst, getMemDisp());
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000293 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
294 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000295
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000296 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
297 assert((N == 1) && "Invalid number of operands!");
298 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
299 }
300
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000301 void addNoSegMemOperands(MCInst &Inst, unsigned N) const {
302 assert((N == 4) && "Invalid number of operands!");
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000303 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
304 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
305 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000306 addExpr(Inst, getMemDisp());
Daniel Dunbar20927f22009-08-07 08:26:05 +0000307 }
308
Chris Lattnerb4307b32010-01-15 19:28:38 +0000309 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
310 X86Operand *Res = new X86Operand(Token, Loc, Loc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000311 Res->Tok.Data = Str.data();
312 Res->Tok.Length = Str.size();
Daniel Dunbar20927f22009-08-07 08:26:05 +0000313 return Res;
314 }
315
Chris Lattner29ef9a22010-01-15 18:51:29 +0000316 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000317 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000318 Res->Reg.RegNo = RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000319 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000320 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000321
Chris Lattnerb4307b32010-01-15 19:28:38 +0000322 static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
323 X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000324 Res->Imm.Val = Val;
325 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000326 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000327
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000328 /// Create an absolute memory operand.
329 static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
330 SMLoc EndLoc) {
331 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
332 Res->Mem.SegReg = 0;
333 Res->Mem.Disp = Disp;
334 Res->Mem.BaseReg = 0;
335 Res->Mem.IndexReg = 0;
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000336 Res->Mem.Scale = 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000337 return Res;
338 }
339
340 /// Create a generalized memory operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000341 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
342 unsigned BaseReg, unsigned IndexReg,
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000343 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000344 // We should never just have a displacement, that should be parsed as an
345 // absolute memory operand.
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000346 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
347
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000348 // The scale should always be one of {1,2,4,8}.
349 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000350 "Invalid scale!");
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000351 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000352 Res->Mem.SegReg = SegReg;
353 Res->Mem.Disp = Disp;
354 Res->Mem.BaseReg = BaseReg;
355 Res->Mem.IndexReg = IndexReg;
356 Res->Mem.Scale = Scale;
357 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000358 }
359};
Daniel Dunbara3af3702009-07-20 18:55:04 +0000360
Chris Lattner37dfdec2009-07-29 06:33:53 +0000361} // end anonymous namespace.
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000362
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000363
Chris Lattner29ef9a22010-01-15 18:51:29 +0000364bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
365 SMLoc &StartLoc, SMLoc &EndLoc) {
Chris Lattner23075742010-01-15 18:27:19 +0000366 RegNo = 0;
Sean Callanan18b83232010-01-19 21:44:56 +0000367 const AsmToken &TokPercent = Parser.getTok();
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000368 assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
Chris Lattner29ef9a22010-01-15 18:51:29 +0000369 StartLoc = TokPercent.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000370 Parser.Lex(); // Eat percent token.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000371
Sean Callanan18b83232010-01-19 21:44:56 +0000372 const AsmToken &Tok = Parser.getTok();
Kevin Enderby0d6cd002009-09-16 17:18:29 +0000373 if (Tok.isNot(AsmToken::Identifier))
374 return Error(Tok.getLoc(), "invalid register name");
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000375
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000376 // FIXME: Validate register for the current architecture; we have to do
377 // validation later, so maybe there is no need for this here.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000378 RegNo = MatchRegisterName(Tok.getString());
Chris Lattnerb8d6e982010-02-09 00:34:28 +0000379
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000380 // Parse %st(1) and "%st" as "%st(0)"
381 if (RegNo == 0 && Tok.getString() == "st") {
382 RegNo = X86::ST0;
383 EndLoc = Tok.getLoc();
384 Parser.Lex(); // Eat 'st'
385
386 // Check to see if we have '(4)' after %st.
387 if (getLexer().isNot(AsmToken::LParen))
388 return false;
389 // Lex the paren.
390 getParser().Lex();
391
392 const AsmToken &IntTok = Parser.getTok();
393 if (IntTok.isNot(AsmToken::Integer))
394 return Error(IntTok.getLoc(), "expected stack index");
395 switch (IntTok.getIntVal()) {
396 case 0: RegNo = X86::ST0; break;
397 case 1: RegNo = X86::ST1; break;
398 case 2: RegNo = X86::ST2; break;
399 case 3: RegNo = X86::ST3; break;
400 case 4: RegNo = X86::ST4; break;
401 case 5: RegNo = X86::ST5; break;
402 case 6: RegNo = X86::ST6; break;
403 case 7: RegNo = X86::ST7; break;
404 default: return Error(IntTok.getLoc(), "invalid stack index");
405 }
406
407 if (getParser().Lex().isNot(AsmToken::RParen))
408 return Error(Parser.getTok().getLoc(), "expected ')'");
409
410 EndLoc = Tok.getLoc();
411 Parser.Lex(); // Eat ')'
412 return false;
413 }
414
Chris Lattner645b2092010-06-24 07:29:18 +0000415 // If this is "db[0-7]", match it as an alias
416 // for dr[0-7].
417 if (RegNo == 0 && Tok.getString().size() == 3 &&
418 Tok.getString().startswith("db")) {
419 switch (Tok.getString()[2]) {
420 case '0': RegNo = X86::DR0; break;
421 case '1': RegNo = X86::DR1; break;
422 case '2': RegNo = X86::DR2; break;
423 case '3': RegNo = X86::DR3; break;
424 case '4': RegNo = X86::DR4; break;
425 case '5': RegNo = X86::DR5; break;
426 case '6': RegNo = X86::DR6; break;
427 case '7': RegNo = X86::DR7; break;
428 }
429
430 if (RegNo != 0) {
431 EndLoc = Tok.getLoc();
432 Parser.Lex(); // Eat it.
433 return false;
434 }
435 }
436
Daniel Dunbar245f0582009-08-08 21:22:41 +0000437 if (RegNo == 0)
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000438 return Error(Tok.getLoc(), "invalid register name");
439
Chris Lattner29ef9a22010-01-15 18:51:29 +0000440 EndLoc = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000441 Parser.Lex(); // Eat identifier token.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000442 return false;
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000443}
444
Chris Lattner309264d2010-01-15 18:44:13 +0000445X86Operand *X86ATTAsmParser::ParseOperand() {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000446 switch (getLexer().getKind()) {
447 default:
Chris Lattnereef6d782010-04-17 18:56:34 +0000448 // Parse a memory operand with no segment register.
449 return ParseMemOperand(0, Parser.getTok().getLoc());
Chris Lattner23075742010-01-15 18:27:19 +0000450 case AsmToken::Percent: {
Chris Lattnereef6d782010-04-17 18:56:34 +0000451 // Read the register.
Chris Lattner23075742010-01-15 18:27:19 +0000452 unsigned RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000453 SMLoc Start, End;
454 if (ParseRegister(RegNo, Start, End)) return 0;
Chris Lattnereef6d782010-04-17 18:56:34 +0000455
456 // If this is a segment register followed by a ':', then this is the start
457 // of a memory reference, otherwise this is a normal register reference.
458 if (getLexer().isNot(AsmToken::Colon))
459 return X86Operand::CreateReg(RegNo, Start, End);
460
461
462 getParser().Lex(); // Eat the colon.
463 return ParseMemOperand(RegNo, Start);
Chris Lattner23075742010-01-15 18:27:19 +0000464 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000465 case AsmToken::Dollar: {
466 // $42 -> immediate.
Sean Callanan18b83232010-01-19 21:44:56 +0000467 SMLoc Start = Parser.getTok().getLoc(), End;
Sean Callananb9a25b72010-01-19 20:27:46 +0000468 Parser.Lex();
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000469 const MCExpr *Val;
Chris Lattner54482b42010-01-15 19:39:23 +0000470 if (getParser().ParseExpression(Val, End))
Chris Lattner309264d2010-01-15 18:44:13 +0000471 return 0;
Chris Lattnerb4307b32010-01-15 19:28:38 +0000472 return X86Operand::CreateImm(Val, Start, End);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000473 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000474 }
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000475}
476
Chris Lattnereef6d782010-04-17 18:56:34 +0000477/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
478/// has already been parsed if present.
479X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
480
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000481 // We have to disambiguate a parenthesized expression "(4+5)" from the start
482 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
Chris Lattner75f265f2010-01-24 01:07:33 +0000483 // only way to do this without lookahead is to eat the '(' and see what is
484 // after it.
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000485 const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000486 if (getLexer().isNot(AsmToken::LParen)) {
Chris Lattner54482b42010-01-15 19:39:23 +0000487 SMLoc ExprEnd;
488 if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000489
490 // After parsing the base expression we could either have a parenthesized
491 // memory address or not. If not, return now. If so, eat the (.
492 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000493 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000494 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000495 return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000496 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000497 }
498
499 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000500 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000501 } else {
502 // Okay, we have a '('. We don't know if this is an expression or not, but
503 // so we have to eat the ( to see beyond it.
Sean Callanan18b83232010-01-19 21:44:56 +0000504 SMLoc LParenLoc = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000505 Parser.Lex(); // Eat the '('.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000506
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000507 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000508 // Nothing to do here, fall into the code below with the '(' part of the
509 // memory operand consumed.
510 } else {
Chris Lattnerb4307b32010-01-15 19:28:38 +0000511 SMLoc ExprEnd;
512
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000513 // It must be an parenthesized expression, parse it now.
Chris Lattnerb4307b32010-01-15 19:28:38 +0000514 if (getParser().ParseParenExpression(Disp, ExprEnd))
Chris Lattner309264d2010-01-15 18:44:13 +0000515 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000516
517 // After parsing the base expression we could either have a parenthesized
518 // memory address or not. If not, return now. If so, eat the (.
519 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000520 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000521 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000522 return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000523 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000524 }
525
526 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000527 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000528 }
529 }
530
531 // If we reached here, then we just ate the ( of the memory operand. Process
532 // the rest of the memory operand.
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000533 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000534
Chris Lattner29ef9a22010-01-15 18:51:29 +0000535 if (getLexer().is(AsmToken::Percent)) {
536 SMLoc L;
537 if (ParseRegister(BaseReg, L, L)) return 0;
538 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000539
540 if (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000541 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000542
543 // Following the comma we should have either an index register, or a scale
544 // value. We don't support the later form, but we want to parse it
545 // correctly.
546 //
547 // Not that even though it would be completely consistent to support syntax
548 // like "1(%eax,,1)", the assembler doesn't.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000549 if (getLexer().is(AsmToken::Percent)) {
Chris Lattner29ef9a22010-01-15 18:51:29 +0000550 SMLoc L;
551 if (ParseRegister(IndexReg, L, L)) return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000552
553 if (getLexer().isNot(AsmToken::RParen)) {
554 // Parse the scale amount:
555 // ::= ',' [scale-expression]
Chris Lattner309264d2010-01-15 18:44:13 +0000556 if (getLexer().isNot(AsmToken::Comma)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000557 Error(Parser.getTok().getLoc(),
Chris Lattner309264d2010-01-15 18:44:13 +0000558 "expected comma in scale expression");
559 return 0;
560 }
Sean Callananb9a25b72010-01-19 20:27:46 +0000561 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000562
563 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000564 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000565
566 int64_t ScaleVal;
567 if (getParser().ParseAbsoluteExpression(ScaleVal))
Chris Lattner309264d2010-01-15 18:44:13 +0000568 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000569
570 // Validate the scale amount.
Chris Lattner309264d2010-01-15 18:44:13 +0000571 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
572 Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
573 return 0;
574 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000575 Scale = (unsigned)ScaleVal;
576 }
577 }
578 } else if (getLexer().isNot(AsmToken::RParen)) {
579 // Otherwise we have the unsupported form of a scale amount without an
580 // index.
Sean Callanan18b83232010-01-19 21:44:56 +0000581 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000582
583 int64_t Value;
584 if (getParser().ParseAbsoluteExpression(Value))
Chris Lattner309264d2010-01-15 18:44:13 +0000585 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000586
Chris Lattner309264d2010-01-15 18:44:13 +0000587 Error(Loc, "cannot have scale factor without index register");
588 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000589 }
590 }
591
592 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
Chris Lattner309264d2010-01-15 18:44:13 +0000593 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000594 Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
Chris Lattner309264d2010-01-15 18:44:13 +0000595 return 0;
596 }
Sean Callanan18b83232010-01-19 21:44:56 +0000597 SMLoc MemEnd = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000598 Parser.Lex(); // Eat the ')'.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000599
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000600 return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
601 MemStart, MemEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000602}
603
Chris Lattner98986712010-01-14 22:21:20 +0000604bool X86ATTAsmParser::
605ParseInstruction(const StringRef &Name, SMLoc NameLoc,
606 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000607 // The various flavors of pushf and popf use Requires<In32BitMode> and
608 // Requires<In64BitMode>, but the assembler doesn't yet implement that.
609 // For now, just do a manual check to prevent silent misencoding.
610 if (Is64Bit) {
611 if (Name == "popfl")
612 return Error(NameLoc, "popfl cannot be encoded in 64-bit mode");
613 else if (Name == "pushfl")
614 return Error(NameLoc, "pushfl cannot be encoded in 64-bit mode");
Kevin Enderby52a18ae2010-07-13 20:05:41 +0000615 else if (Name == "pusha")
616 return Error(NameLoc, "pusha cannot be encoded in 64-bit mode");
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000617 } else {
618 if (Name == "popfq")
619 return Error(NameLoc, "popfq cannot be encoded in 32-bit mode");
620 else if (Name == "pushfq")
621 return Error(NameLoc, "pushfq cannot be encoded in 32-bit mode");
622 }
623
Kevin Enderby09712b52010-06-08 23:48:44 +0000624 // The "Jump if rCX Zero" form jcxz is not allowed in 64-bit mode and
625 // the form jrcxz is not allowed in 32-bit mode.
626 if (Is64Bit) {
627 if (Name == "jcxz")
628 return Error(NameLoc, "jcxz cannot be encoded in 64-bit mode");
629 } else {
630 if (Name == "jrcxz")
631 return Error(NameLoc, "jrcxz cannot be encoded in 32-bit mode");
632 }
633
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000634 // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
635 // represent alternative syntaxes in the .td file, without requiring
636 // instruction duplication.
637 StringRef PatchedName = StringSwitch<StringRef>(Name)
638 .Case("sal", "shl")
639 .Case("salb", "shlb")
640 .Case("sall", "shll")
641 .Case("salq", "shlq")
642 .Case("salw", "shlw")
643 .Case("repe", "rep")
644 .Case("repz", "rep")
645 .Case("repnz", "repne")
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000646 .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
647 .Case("popf", Is64Bit ? "popfq" : "popfl")
Kevin Enderby9d31d792010-05-21 23:01:38 +0000648 .Case("retl", Is64Bit ? "retl" : "ret")
649 .Case("retq", Is64Bit ? "ret" : "retq")
Daniel Dunbar4c361972010-05-22 06:37:33 +0000650 .Case("setz", "sete")
651 .Case("setnz", "setne")
652 .Case("jz", "je")
653 .Case("jnz", "jne")
Kevin Enderbybd658912010-05-27 21:33:19 +0000654 .Case("jc", "jb")
Kevin Enderby09712b52010-06-08 23:48:44 +0000655 // FIXME: in 32-bit mode jcxz requires an AdSize prefix. In 64-bit mode
656 // jecxz requires an AdSize prefix but jecxz does not have a prefix in
657 // 32-bit mode.
Kevin Enderbybd658912010-05-27 21:33:19 +0000658 .Case("jecxz", "jcxz")
Kevin Enderby09712b52010-06-08 23:48:44 +0000659 .Case("jrcxz", "jcxz")
Kevin Enderbybd658912010-05-27 21:33:19 +0000660 .Case("jna", "jbe")
661 .Case("jnae", "jb")
662 .Case("jnb", "jae")
663 .Case("jnbe", "ja")
664 .Case("jnc", "jae")
665 .Case("jng", "jle")
666 .Case("jnge", "jl")
667 .Case("jnl", "jge")
668 .Case("jnle", "jg")
669 .Case("jpe", "jp")
670 .Case("jpo", "jnp")
Kevin Enderbyca956dc2010-05-24 20:32:23 +0000671 .Case("cmovcl", "cmovbl")
672 .Case("cmovcl", "cmovbl")
673 .Case("cmovnal", "cmovbel")
674 .Case("cmovnbl", "cmovael")
675 .Case("cmovnbel", "cmoval")
676 .Case("cmovncl", "cmovael")
677 .Case("cmovngl", "cmovlel")
678 .Case("cmovnl", "cmovgel")
679 .Case("cmovngl", "cmovlel")
680 .Case("cmovngel", "cmovll")
681 .Case("cmovnll", "cmovgel")
682 .Case("cmovnlel", "cmovgl")
683 .Case("cmovnzl", "cmovnel")
684 .Case("cmovzl", "cmovel")
Kevin Enderby5e394422010-05-28 20:59:10 +0000685 .Case("fwait", "wait")
Kevin Enderby31cc9652010-05-28 21:20:21 +0000686 .Case("movzx", "movzb")
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000687 .Default(Name);
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000688
689 // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
690 const MCExpr *ExtraImmOp = 0;
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000691 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000692 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
693 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000694 bool IsVCMP = PatchedName.startswith("vcmp");
695 unsigned SSECCIdx = IsVCMP ? 4 : 3;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000696 unsigned SSEComparisonCode = StringSwitch<unsigned>(
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000697 PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
Bruno Cardoso Lopescc69e132010-07-07 22:24:03 +0000698 .Case("eq", 0)
699 .Case("lt", 1)
700 .Case("le", 2)
701 .Case("unord", 3)
702 .Case("neq", 4)
703 .Case("nlt", 5)
704 .Case("nle", 6)
705 .Case("ord", 7)
706 .Case("eq_uq", 8)
707 .Case("nge", 9)
708 .Case("ngt", 0x0A)
709 .Case("false", 0x0B)
710 .Case("neq_oq", 0x0C)
711 .Case("ge", 0x0D)
712 .Case("gt", 0x0E)
713 .Case("true", 0x0F)
714 .Case("eq_os", 0x10)
715 .Case("lt_oq", 0x11)
716 .Case("le_oq", 0x12)
717 .Case("unord_s", 0x13)
718 .Case("neq_us", 0x14)
719 .Case("nlt_uq", 0x15)
720 .Case("nle_uq", 0x16)
721 .Case("ord_s", 0x17)
722 .Case("eq_us", 0x18)
723 .Case("nge_uq", 0x19)
724 .Case("ngt_uq", 0x1A)
725 .Case("false_os", 0x1B)
726 .Case("neq_os", 0x1C)
727 .Case("ge_oq", 0x1D)
728 .Case("gt_oq", 0x1E)
729 .Case("true_us", 0x1F)
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000730 .Default(~0U);
731 if (SSEComparisonCode != ~0U) {
732 ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode,
733 getParser().getContext());
734 if (PatchedName.endswith("ss")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000735 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000736 } else if (PatchedName.endswith("sd")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000737 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000738 } else if (PatchedName.endswith("ps")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000739 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000740 } else {
741 assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000742 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000743 }
744 }
745 }
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000746 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000747
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000748 if (ExtraImmOp)
749 Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
750
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000751 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000752
753 // Parse '*' modifier.
754 if (getLexer().is(AsmToken::Star)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000755 SMLoc Loc = Parser.getTok().getLoc();
Chris Lattnerb4307b32010-01-15 19:28:38 +0000756 Operands.push_back(X86Operand::CreateToken("*", Loc));
Sean Callananb9a25b72010-01-19 20:27:46 +0000757 Parser.Lex(); // Eat the star.
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000758 }
759
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000760 // Read the first operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000761 if (X86Operand *Op = ParseOperand())
762 Operands.push_back(Op);
763 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000764 return true;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000765
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000766 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000767 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000768
769 // Parse and remember the operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000770 if (X86Operand *Op = ParseOperand())
771 Operands.push_back(Op);
772 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000773 return true;
774 }
775 }
776
Daniel Dunbard5e77052010-03-13 00:47:29 +0000777 // FIXME: Hack to handle recognizing s{hr,ar,hl}? $1.
778 if ((Name.startswith("shr") || Name.startswith("sar") ||
779 Name.startswith("shl")) &&
780 Operands.size() == 3 &&
781 static_cast<X86Operand*>(Operands[1])->isImm() &&
782 isa<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm()) &&
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000783 cast<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm())->getValue() == 1) {
784 delete Operands[1];
Daniel Dunbard5e77052010-03-13 00:47:29 +0000785 Operands.erase(Operands.begin() + 1);
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000786 }
Daniel Dunbard5e77052010-03-13 00:47:29 +0000787
Kevin Enderbycf50a532010-05-25 20:52:34 +0000788 // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
789 // "f{mul*,add*,sub*,div*} $op"
790 if ((Name.startswith("fmul") || Name.startswith("fadd") ||
791 Name.startswith("fsub") || Name.startswith("fdiv")) &&
792 Operands.size() == 3 &&
793 static_cast<X86Operand*>(Operands[2])->isReg() &&
794 static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
795 delete Operands[2];
796 Operands.erase(Operands.begin() + 2);
797 }
798
Chris Lattner98986712010-01-14 22:21:20 +0000799 return false;
Daniel Dunbara3af3702009-07-20 18:55:04 +0000800}
801
Kevin Enderby9c656452009-09-10 20:51:44 +0000802bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
803 StringRef IDVal = DirectiveID.getIdentifier();
804 if (IDVal == ".word")
805 return ParseDirectiveWord(2, DirectiveID.getLoc());
806 return true;
807}
808
809/// ParseDirectiveWord
810/// ::= .word [ expression (, expression)* ]
811bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
812 if (getLexer().isNot(AsmToken::EndOfStatement)) {
813 for (;;) {
814 const MCExpr *Value;
815 if (getParser().ParseExpression(Value))
816 return true;
817
Chris Lattneraaec2052010-01-19 19:46:13 +0000818 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
Kevin Enderby9c656452009-09-10 20:51:44 +0000819
820 if (getLexer().is(AsmToken::EndOfStatement))
821 break;
822
823 // FIXME: Improve diagnostic.
824 if (getLexer().isNot(AsmToken::Comma))
825 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000826 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000827 }
828 }
829
Sean Callananb9a25b72010-01-19 20:27:46 +0000830 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000831 return false;
832}
833
Chris Lattnerb5505d02010-05-13 00:02:47 +0000834/// LowerMOffset - Lower an 'moffset' form of an instruction, which just has a
835/// imm operand, to having "rm" or "mr" operands with the offset in the disp
836/// field.
837static void LowerMOffset(MCInst &Inst, unsigned Opc, unsigned RegNo,
838 bool isMR) {
839 MCOperand Disp = Inst.getOperand(0);
840
841 // Start over with an empty instruction.
842 Inst = MCInst();
843 Inst.setOpcode(Opc);
844
845 if (!isMR)
846 Inst.addOperand(MCOperand::CreateReg(RegNo));
847
848 // Add the mem operand.
849 Inst.addOperand(MCOperand::CreateReg(0)); // Segment
850 Inst.addOperand(MCOperand::CreateImm(1)); // Scale
851 Inst.addOperand(MCOperand::CreateReg(0)); // IndexReg
852 Inst.addOperand(Disp); // Displacement
853 Inst.addOperand(MCOperand::CreateReg(0)); // BaseReg
854
855 if (isMR)
856 Inst.addOperand(MCOperand::CreateReg(RegNo));
857}
858
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000859// FIXME: Custom X86 cleanup function to implement a temporary hack to handle
860// matching INCL/DECL correctly for x86_64. This needs to be replaced by a
861// proper mechanism for supporting (ambiguous) feature dependent instructions.
862void X86ATTAsmParser::InstructionCleanup(MCInst &Inst) {
863 if (!Is64Bit) return;
864
865 switch (Inst.getOpcode()) {
866 case X86::DEC16r: Inst.setOpcode(X86::DEC64_16r); break;
867 case X86::DEC16m: Inst.setOpcode(X86::DEC64_16m); break;
868 case X86::DEC32r: Inst.setOpcode(X86::DEC64_32r); break;
869 case X86::DEC32m: Inst.setOpcode(X86::DEC64_32m); break;
870 case X86::INC16r: Inst.setOpcode(X86::INC64_16r); break;
871 case X86::INC16m: Inst.setOpcode(X86::INC64_16m); break;
872 case X86::INC32r: Inst.setOpcode(X86::INC64_32r); break;
873 case X86::INC32m: Inst.setOpcode(X86::INC64_32m); break;
Chris Lattnerb5505d02010-05-13 00:02:47 +0000874
875 // moffset instructions are x86-32 only.
876 case X86::MOV8o8a: LowerMOffset(Inst, X86::MOV8rm , X86::AL , false); break;
877 case X86::MOV16o16a: LowerMOffset(Inst, X86::MOV16rm, X86::AX , false); break;
878 case X86::MOV32o32a: LowerMOffset(Inst, X86::MOV32rm, X86::EAX, false); break;
879 case X86::MOV8ao8: LowerMOffset(Inst, X86::MOV8mr , X86::AL , true); break;
880 case X86::MOV16ao16: LowerMOffset(Inst, X86::MOV16mr, X86::AX , true); break;
881 case X86::MOV32ao32: LowerMOffset(Inst, X86::MOV32mr, X86::EAX, true); break;
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000882 }
883}
884
Daniel Dunbarc918d602010-05-04 16:12:42 +0000885bool
886X86ATTAsmParser::MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*>
887 &Operands,
888 MCInst &Inst) {
889 // First, try a direct match.
890 if (!MatchInstructionImpl(Operands, Inst))
891 return false;
892
893 // Ignore anything which is obviously not a suffix match.
894 if (Operands.size() == 0)
895 return true;
896 X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
897 if (!Op->isToken() || Op->getToken().size() > 15)
898 return true;
899
900 // FIXME: Ideally, we would only attempt suffix matches for things which are
901 // valid prefixes, and we could just infer the right unambiguous
902 // type. However, that requires substantially more matcher support than the
903 // following hack.
904
905 // Change the operand to point to a temporary token.
906 char Tmp[16];
907 StringRef Base = Op->getToken();
908 memcpy(Tmp, Base.data(), Base.size());
909 Op->setTokenValue(StringRef(Tmp, Base.size() + 1));
910
911 // Check for the various suffix matches.
912 Tmp[Base.size()] = 'b';
913 bool MatchB = MatchInstructionImpl(Operands, Inst);
914 Tmp[Base.size()] = 'w';
915 bool MatchW = MatchInstructionImpl(Operands, Inst);
916 Tmp[Base.size()] = 'l';
917 bool MatchL = MatchInstructionImpl(Operands, Inst);
Daniel Dunbar04814492010-05-12 00:54:20 +0000918 Tmp[Base.size()] = 'q';
919 bool MatchQ = MatchInstructionImpl(Operands, Inst);
Daniel Dunbarc918d602010-05-04 16:12:42 +0000920
921 // Restore the old token.
922 Op->setTokenValue(Base);
923
924 // If exactly one matched, then we treat that as a successful match (and the
925 // instruction will already have been filled in correctly, since the failing
926 // matches won't have modified it).
Daniel Dunbar04814492010-05-12 00:54:20 +0000927 if (MatchB + MatchW + MatchL + MatchQ == 3)
Daniel Dunbarc918d602010-05-04 16:12:42 +0000928 return false;
929
Daniel Dunbarc918d602010-05-04 16:12:42 +0000930 // Otherwise, the match failed.
931 return true;
932}
933
934
Sean Callanane88f5522010-01-23 02:43:15 +0000935extern "C" void LLVMInitializeX86AsmLexer();
936
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000937// Force static initialization.
938extern "C" void LLVMInitializeX86AsmParser() {
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000939 RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
940 RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
Sean Callanane88f5522010-01-23 02:43:15 +0000941 LLVMInitializeX86AsmLexer();
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000942}
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000943
944#include "X86GenAsmMatcher.inc"