blob: 3095bdb915fe3202dbba1b9a744917a4bb9421bb [file] [log] [blame]
Daniel Dunbar71475772009-07-17 20:42:00 +00001//===-- X86AsmParser.cpp - Parse X86 assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattnerf29c0b62010-01-14 22:21:20 +000010#include "llvm/Target/TargetAsmParser.h"
Daniel Dunbar67038c12009-07-18 23:03:22 +000011#include "X86.h"
Daniel Dunbareefe8612010-07-19 05:44:09 +000012#include "X86Subtarget.h"
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +000013#include "llvm/ADT/SmallVector.h"
Daniel Dunbar3e0c9792010-02-10 21:19:28 +000014#include "llvm/ADT/StringSwitch.h"
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000015#include "llvm/ADT/Twine.h"
Kevin Enderbyce4bec82009-09-10 20:51:44 +000016#include "llvm/MC/MCStreamer.h"
Daniel Dunbar73da11e2009-08-31 08:08:38 +000017#include "llvm/MC/MCExpr.h"
Daniel Dunbarb6d6aa22009-07-31 02:32:59 +000018#include "llvm/MC/MCInst.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
20#include "llvm/MC/MCParser/MCAsmParser.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000022#include "llvm/Support/SourceMgr.h"
Daniel Dunbar71475772009-07-17 20:42:00 +000023#include "llvm/Target/TargetRegistry.h"
24#include "llvm/Target/TargetAsmParser.h"
25using namespace llvm;
26
27namespace {
Benjamin Kramerb60210e2009-07-31 11:35:26 +000028struct X86Operand;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000029
30class X86ATTAsmParser : public TargetAsmParser {
31 MCAsmParser &Parser;
Daniel Dunbar419197c2010-07-19 00:33:49 +000032 TargetMachine &TM;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000033
Daniel Dunbar63ec0932010-03-18 20:06:02 +000034protected:
35 unsigned Is64Bit : 1;
36
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000037private:
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000038 MCAsmParser &getParser() const { return Parser; }
39
40 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
41
42 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
43
44 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
45
Chris Lattner0c2538f2010-01-15 18:51:29 +000046 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000047
Chris Lattnera2bbb7c2010-01-15 18:44:13 +000048 X86Operand *ParseOperand();
Chris Lattnerb9270732010-04-17 18:56:34 +000049 X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
Kevin Enderbyce4bec82009-09-10 20:51:44 +000050
51 bool ParseDirectiveWord(unsigned Size, SMLoc L);
52
Chris Lattnerf29c0b62010-01-14 22:21:20 +000053 bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbare10787e2009-08-07 08:26:05 +000054 MCInst &Inst);
55
Daniel Dunbareefe8612010-07-19 05:44:09 +000056 /// @name Auto-generated Matcher Functions
57 /// {
58
59 unsigned ComputeAvailableFeatures(const X86Subtarget *Subtarget) const;
60
Daniel Dunbar9b816a12010-05-04 16:12:42 +000061 bool MatchInstructionImpl(
62 const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst);
63
Daniel Dunbar00331992009-07-29 00:02:19 +000064 /// }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000065
66public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000067 X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
Daniel Dunbareefe8612010-07-19 05:44:09 +000068 : TargetAsmParser(T), Parser(_Parser), TM(TM) {
69
70 // Initialize the set of available features.
71 setAvailableFeatures(ComputeAvailableFeatures(
72 &TM.getSubtarget<X86Subtarget>()));
73 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000074
Benjamin Kramer92d89982010-07-14 22:38:02 +000075 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattnerf29c0b62010-01-14 22:21:20 +000076 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderbyce4bec82009-09-10 20:51:44 +000077
78 virtual bool ParseDirective(AsmToken DirectiveID);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000079};
Daniel Dunbar63ec0932010-03-18 20:06:02 +000080
81class X86_32ATTAsmParser : public X86ATTAsmParser {
82public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000083 X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
84 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbar63ec0932010-03-18 20:06:02 +000085 Is64Bit = false;
86 }
87};
88
89class X86_64ATTAsmParser : public X86ATTAsmParser {
90public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000091 X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
92 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbar63ec0932010-03-18 20:06:02 +000093 Is64Bit = true;
94 }
95};
96
Chris Lattner4eb9df02009-07-29 06:33:53 +000097} // end anonymous namespace
98
Sean Callanan86c11812010-01-23 00:40:33 +000099/// @name Auto-generated Match Functions
100/// {
101
Chris Lattner60db0a62010-02-09 00:34:28 +0000102static unsigned MatchRegisterName(StringRef Name);
Sean Callanan86c11812010-01-23 00:40:33 +0000103
104/// }
Chris Lattner4eb9df02009-07-29 06:33:53 +0000105
106namespace {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000107
108/// X86Operand - Instances of this class represent a parsed X86 machine
109/// instruction.
Chris Lattner872501b2010-01-14 21:20:55 +0000110struct X86Operand : public MCParsedAsmOperand {
Chris Lattner86e61532010-01-15 19:06:59 +0000111 enum KindTy {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000112 Token,
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000113 Register,
114 Immediate,
115 Memory
116 } Kind;
117
Chris Lattner0c2538f2010-01-15 18:51:29 +0000118 SMLoc StartLoc, EndLoc;
119
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000120 union {
121 struct {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000122 const char *Data;
123 unsigned Length;
124 } Tok;
125
126 struct {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000127 unsigned RegNo;
128 } Reg;
129
130 struct {
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000131 const MCExpr *Val;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000132 } Imm;
133
134 struct {
135 unsigned SegReg;
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000136 const MCExpr *Disp;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000137 unsigned BaseReg;
138 unsigned IndexReg;
139 unsigned Scale;
140 } Mem;
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +0000141 };
Daniel Dunbar71475772009-07-17 20:42:00 +0000142
Chris Lattner015cfb12010-01-15 19:33:43 +0000143 X86Operand(KindTy K, SMLoc Start, SMLoc End)
Chris Lattner86e61532010-01-15 19:06:59 +0000144 : Kind(K), StartLoc(Start), EndLoc(End) {}
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000145
Chris Lattner86e61532010-01-15 19:06:59 +0000146 /// getStartLoc - Get the location of the first token of this operand.
147 SMLoc getStartLoc() const { return StartLoc; }
148 /// getEndLoc - Get the location of the last token of this operand.
149 SMLoc getEndLoc() const { return EndLoc; }
150
Daniel Dunbare10787e2009-08-07 08:26:05 +0000151 StringRef getToken() const {
152 assert(Kind == Token && "Invalid access!");
153 return StringRef(Tok.Data, Tok.Length);
154 }
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000155 void setTokenValue(StringRef Value) {
156 assert(Kind == Token && "Invalid access!");
157 Tok.Data = Value.data();
158 Tok.Length = Value.size();
159 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000160
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000161 unsigned getReg() const {
162 assert(Kind == Register && "Invalid access!");
163 return Reg.RegNo;
164 }
Daniel Dunbarf59ee962009-07-28 20:47:52 +0000165
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000166 const MCExpr *getImm() const {
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000167 assert(Kind == Immediate && "Invalid access!");
168 return Imm.Val;
169 }
170
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000171 const MCExpr *getMemDisp() const {
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000172 assert(Kind == Memory && "Invalid access!");
173 return Mem.Disp;
174 }
175 unsigned getMemSegReg() const {
176 assert(Kind == Memory && "Invalid access!");
177 return Mem.SegReg;
178 }
179 unsigned getMemBaseReg() const {
180 assert(Kind == Memory && "Invalid access!");
181 return Mem.BaseReg;
182 }
183 unsigned getMemIndexReg() const {
184 assert(Kind == Memory && "Invalid access!");
185 return Mem.IndexReg;
186 }
187 unsigned getMemScale() const {
188 assert(Kind == Memory && "Invalid access!");
189 return Mem.Scale;
190 }
191
Daniel Dunbar541efcc2009-08-08 07:50:56 +0000192 bool isToken() const {return Kind == Token; }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000193
194 bool isImm() const { return Kind == Immediate; }
195
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000196 bool isImmSExti16i8() const {
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000197 if (!isImm())
198 return false;
199
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000200 // If this isn't a constant expr, just assume it fits and let relaxation
201 // handle it.
202 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
203 if (!CE)
204 return true;
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000205
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000206 // Otherwise, check the value is in a range that makes sense for this
207 // extension.
208 uint64_t Value = CE->getValue();
209 return (( Value <= 0x000000000000007FULL)||
210 (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)||
211 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000212 }
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000213 bool isImmSExti32i8() const {
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000214 if (!isImm())
215 return false;
216
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000217 // If this isn't a constant expr, just assume it fits and let relaxation
218 // handle it.
219 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
220 if (!CE)
221 return true;
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000222
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000223 // Otherwise, check the value is in a range that makes sense for this
224 // extension.
225 uint64_t Value = CE->getValue();
226 return (( Value <= 0x000000000000007FULL)||
227 (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
228 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
229 }
230 bool isImmSExti64i8() const {
231 if (!isImm())
232 return false;
233
234 // If this isn't a constant expr, just assume it fits and let relaxation
235 // handle it.
236 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
237 if (!CE)
238 return true;
239
240 // Otherwise, check the value is in a range that makes sense for this
241 // extension.
242 uint64_t Value = CE->getValue();
243 return (( Value <= 0x000000000000007FULL)||
244 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
245 }
246 bool isImmSExti64i32() const {
247 if (!isImm())
248 return false;
249
250 // If this isn't a constant expr, just assume it fits and let relaxation
251 // handle it.
252 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
253 if (!CE)
254 return true;
255
256 // Otherwise, check the value is in a range that makes sense for this
257 // extension.
258 uint64_t Value = CE->getValue();
259 return (( Value <= 0x000000007FFFFFFFULL)||
260 (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000261 }
262
Daniel Dunbare10787e2009-08-07 08:26:05 +0000263 bool isMem() const { return Kind == Memory; }
264
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000265 bool isAbsMem() const {
266 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
Daniel Dunbar3184f222010-02-02 21:44:16 +0000267 !getMemIndexReg() && getMemScale() == 1;
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000268 }
269
Daniel Dunbara97adee2010-01-30 00:24:00 +0000270 bool isNoSegMem() const {
271 return Kind == Memory && !getMemSegReg();
272 }
273
Daniel Dunbare10787e2009-08-07 08:26:05 +0000274 bool isReg() const { return Kind == Register; }
275
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000276 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
277 // Add as immediates when possible.
278 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
279 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
280 else
281 Inst.addOperand(MCOperand::CreateExpr(Expr));
282 }
283
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000284 void addRegOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000285 assert(N == 1 && "Invalid number of operands!");
286 Inst.addOperand(MCOperand::CreateReg(getReg()));
287 }
288
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000289 void addImmOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000290 assert(N == 1 && "Invalid number of operands!");
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000291 addExpr(Inst, getImm());
Daniel Dunbare10787e2009-08-07 08:26:05 +0000292 }
293
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000294 void addMemOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbara97adee2010-01-30 00:24:00 +0000295 assert((N == 5) && "Invalid number of operands!");
Daniel Dunbare10787e2009-08-07 08:26:05 +0000296 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
297 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
298 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000299 addExpr(Inst, getMemDisp());
Daniel Dunbara97adee2010-01-30 00:24:00 +0000300 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
301 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000302
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000303 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
304 assert((N == 1) && "Invalid number of operands!");
305 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
306 }
307
Daniel Dunbara97adee2010-01-30 00:24:00 +0000308 void addNoSegMemOperands(MCInst &Inst, unsigned N) const {
309 assert((N == 4) && "Invalid number of operands!");
Daniel Dunbara97adee2010-01-30 00:24:00 +0000310 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
311 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
312 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000313 addExpr(Inst, getMemDisp());
Daniel Dunbare10787e2009-08-07 08:26:05 +0000314 }
315
Chris Lattner528d00b2010-01-15 19:28:38 +0000316 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
317 X86Operand *Res = new X86Operand(Token, Loc, Loc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000318 Res->Tok.Data = Str.data();
319 Res->Tok.Length = Str.size();
Daniel Dunbare10787e2009-08-07 08:26:05 +0000320 return Res;
321 }
322
Chris Lattner0c2538f2010-01-15 18:51:29 +0000323 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
Chris Lattner86e61532010-01-15 19:06:59 +0000324 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000325 Res->Reg.RegNo = RegNo;
Chris Lattner0c2538f2010-01-15 18:51:29 +0000326 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000327 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000328
Chris Lattner528d00b2010-01-15 19:28:38 +0000329 static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
330 X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000331 Res->Imm.Val = Val;
332 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000333 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000334
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000335 /// Create an absolute memory operand.
336 static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
337 SMLoc EndLoc) {
338 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
339 Res->Mem.SegReg = 0;
340 Res->Mem.Disp = Disp;
341 Res->Mem.BaseReg = 0;
342 Res->Mem.IndexReg = 0;
Daniel Dunbar3184f222010-02-02 21:44:16 +0000343 Res->Mem.Scale = 1;
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000344 return Res;
345 }
346
347 /// Create a generalized memory operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000348 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
349 unsigned BaseReg, unsigned IndexReg,
Chris Lattner015cfb12010-01-15 19:33:43 +0000350 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000351 // We should never just have a displacement, that should be parsed as an
352 // absolute memory operand.
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000353 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
354
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000355 // The scale should always be one of {1,2,4,8}.
356 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000357 "Invalid scale!");
Chris Lattner015cfb12010-01-15 19:33:43 +0000358 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000359 Res->Mem.SegReg = SegReg;
360 Res->Mem.Disp = Disp;
361 Res->Mem.BaseReg = BaseReg;
362 Res->Mem.IndexReg = IndexReg;
363 Res->Mem.Scale = Scale;
364 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000365 }
366};
Daniel Dunbar3c2a8932009-07-20 18:55:04 +0000367
Chris Lattner4eb9df02009-07-29 06:33:53 +0000368} // end anonymous namespace.
Daniel Dunbarf59ee962009-07-28 20:47:52 +0000369
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000370
Chris Lattner0c2538f2010-01-15 18:51:29 +0000371bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
372 SMLoc &StartLoc, SMLoc &EndLoc) {
Chris Lattnercc2ad082010-01-15 18:27:19 +0000373 RegNo = 0;
Sean Callanan936b0d32010-01-19 21:44:56 +0000374 const AsmToken &TokPercent = Parser.getTok();
Kevin Enderby7d912182009-09-03 17:15:07 +0000375 assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
Chris Lattner0c2538f2010-01-15 18:51:29 +0000376 StartLoc = TokPercent.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000377 Parser.Lex(); // Eat percent token.
Kevin Enderby7d912182009-09-03 17:15:07 +0000378
Sean Callanan936b0d32010-01-19 21:44:56 +0000379 const AsmToken &Tok = Parser.getTok();
Kevin Enderbyc0edda32009-09-16 17:18:29 +0000380 if (Tok.isNot(AsmToken::Identifier))
381 return Error(Tok.getLoc(), "invalid register name");
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000382
Daniel Dunbar00331992009-07-29 00:02:19 +0000383 // FIXME: Validate register for the current architecture; we have to do
384 // validation later, so maybe there is no need for this here.
Kevin Enderby7d912182009-09-03 17:15:07 +0000385 RegNo = MatchRegisterName(Tok.getString());
Chris Lattner60db0a62010-02-09 00:34:28 +0000386
Chris Lattnerd00faaa2010-02-09 00:49:22 +0000387 // Parse %st(1) and "%st" as "%st(0)"
388 if (RegNo == 0 && Tok.getString() == "st") {
389 RegNo = X86::ST0;
390 EndLoc = Tok.getLoc();
391 Parser.Lex(); // Eat 'st'
392
393 // Check to see if we have '(4)' after %st.
394 if (getLexer().isNot(AsmToken::LParen))
395 return false;
396 // Lex the paren.
397 getParser().Lex();
398
399 const AsmToken &IntTok = Parser.getTok();
400 if (IntTok.isNot(AsmToken::Integer))
401 return Error(IntTok.getLoc(), "expected stack index");
402 switch (IntTok.getIntVal()) {
403 case 0: RegNo = X86::ST0; break;
404 case 1: RegNo = X86::ST1; break;
405 case 2: RegNo = X86::ST2; break;
406 case 3: RegNo = X86::ST3; break;
407 case 4: RegNo = X86::ST4; break;
408 case 5: RegNo = X86::ST5; break;
409 case 6: RegNo = X86::ST6; break;
410 case 7: RegNo = X86::ST7; break;
411 default: return Error(IntTok.getLoc(), "invalid stack index");
412 }
413
414 if (getParser().Lex().isNot(AsmToken::RParen))
415 return Error(Parser.getTok().getLoc(), "expected ')'");
416
417 EndLoc = Tok.getLoc();
418 Parser.Lex(); // Eat ')'
419 return false;
420 }
421
Chris Lattner80486622010-06-24 07:29:18 +0000422 // If this is "db[0-7]", match it as an alias
423 // for dr[0-7].
424 if (RegNo == 0 && Tok.getString().size() == 3 &&
425 Tok.getString().startswith("db")) {
426 switch (Tok.getString()[2]) {
427 case '0': RegNo = X86::DR0; break;
428 case '1': RegNo = X86::DR1; break;
429 case '2': RegNo = X86::DR2; break;
430 case '3': RegNo = X86::DR3; break;
431 case '4': RegNo = X86::DR4; break;
432 case '5': RegNo = X86::DR5; break;
433 case '6': RegNo = X86::DR6; break;
434 case '7': RegNo = X86::DR7; break;
435 }
436
437 if (RegNo != 0) {
438 EndLoc = Tok.getLoc();
439 Parser.Lex(); // Eat it.
440 return false;
441 }
442 }
443
Daniel Dunbar66f4f542009-08-08 21:22:41 +0000444 if (RegNo == 0)
Daniel Dunbar00331992009-07-29 00:02:19 +0000445 return Error(Tok.getLoc(), "invalid register name");
446
Chris Lattner0c2538f2010-01-15 18:51:29 +0000447 EndLoc = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000448 Parser.Lex(); // Eat identifier token.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000449 return false;
Daniel Dunbar71475772009-07-17 20:42:00 +0000450}
451
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000452X86Operand *X86ATTAsmParser::ParseOperand() {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000453 switch (getLexer().getKind()) {
454 default:
Chris Lattnerb9270732010-04-17 18:56:34 +0000455 // Parse a memory operand with no segment register.
456 return ParseMemOperand(0, Parser.getTok().getLoc());
Chris Lattnercc2ad082010-01-15 18:27:19 +0000457 case AsmToken::Percent: {
Chris Lattnerb9270732010-04-17 18:56:34 +0000458 // Read the register.
Chris Lattnercc2ad082010-01-15 18:27:19 +0000459 unsigned RegNo;
Chris Lattner0c2538f2010-01-15 18:51:29 +0000460 SMLoc Start, End;
461 if (ParseRegister(RegNo, Start, End)) return 0;
Chris Lattnerb9270732010-04-17 18:56:34 +0000462
463 // If this is a segment register followed by a ':', then this is the start
464 // of a memory reference, otherwise this is a normal register reference.
465 if (getLexer().isNot(AsmToken::Colon))
466 return X86Operand::CreateReg(RegNo, Start, End);
467
468
469 getParser().Lex(); // Eat the colon.
470 return ParseMemOperand(RegNo, Start);
Chris Lattnercc2ad082010-01-15 18:27:19 +0000471 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000472 case AsmToken::Dollar: {
473 // $42 -> immediate.
Sean Callanan936b0d32010-01-19 21:44:56 +0000474 SMLoc Start = Parser.getTok().getLoc(), End;
Sean Callanana83fd7d2010-01-19 20:27:46 +0000475 Parser.Lex();
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000476 const MCExpr *Val;
Chris Lattnere17df0b2010-01-15 19:39:23 +0000477 if (getParser().ParseExpression(Val, End))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000478 return 0;
Chris Lattner528d00b2010-01-15 19:28:38 +0000479 return X86Operand::CreateImm(Val, Start, End);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000480 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000481 }
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +0000482}
483
Chris Lattnerb9270732010-04-17 18:56:34 +0000484/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
485/// has already been parsed if present.
486X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
487
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000488 // We have to disambiguate a parenthesized expression "(4+5)" from the start
489 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
Chris Lattner807a3bc2010-01-24 01:07:33 +0000490 // only way to do this without lookahead is to eat the '(' and see what is
491 // after it.
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000492 const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000493 if (getLexer().isNot(AsmToken::LParen)) {
Chris Lattnere17df0b2010-01-15 19:39:23 +0000494 SMLoc ExprEnd;
495 if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000496
497 // After parsing the base expression we could either have a parenthesized
498 // memory address or not. If not, return now. If so, eat the (.
499 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000500 // Unless we have a segment register, treat this as an immediate.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000501 if (SegReg == 0)
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000502 return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
Chris Lattner015cfb12010-01-15 19:33:43 +0000503 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000504 }
505
506 // Eat the '('.
Sean Callanana83fd7d2010-01-19 20:27:46 +0000507 Parser.Lex();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000508 } else {
509 // Okay, we have a '('. We don't know if this is an expression or not, but
510 // so we have to eat the ( to see beyond it.
Sean Callanan936b0d32010-01-19 21:44:56 +0000511 SMLoc LParenLoc = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000512 Parser.Lex(); // Eat the '('.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000513
Kevin Enderby7d912182009-09-03 17:15:07 +0000514 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000515 // Nothing to do here, fall into the code below with the '(' part of the
516 // memory operand consumed.
517 } else {
Chris Lattner528d00b2010-01-15 19:28:38 +0000518 SMLoc ExprEnd;
519
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000520 // It must be an parenthesized expression, parse it now.
Chris Lattner528d00b2010-01-15 19:28:38 +0000521 if (getParser().ParseParenExpression(Disp, ExprEnd))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000522 return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000523
524 // After parsing the base expression we could either have a parenthesized
525 // memory address or not. If not, return now. If so, eat the (.
526 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000527 // Unless we have a segment register, treat this as an immediate.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000528 if (SegReg == 0)
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000529 return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
Chris Lattner015cfb12010-01-15 19:33:43 +0000530 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000531 }
532
533 // Eat the '('.
Sean Callanana83fd7d2010-01-19 20:27:46 +0000534 Parser.Lex();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000535 }
536 }
537
538 // If we reached here, then we just ate the ( of the memory operand. Process
539 // the rest of the memory operand.
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000540 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000541
Chris Lattner0c2538f2010-01-15 18:51:29 +0000542 if (getLexer().is(AsmToken::Percent)) {
543 SMLoc L;
544 if (ParseRegister(BaseReg, L, L)) return 0;
545 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000546
547 if (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +0000548 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000549
550 // Following the comma we should have either an index register, or a scale
551 // value. We don't support the later form, but we want to parse it
552 // correctly.
553 //
554 // Not that even though it would be completely consistent to support syntax
555 // like "1(%eax,,1)", the assembler doesn't.
Kevin Enderby7d912182009-09-03 17:15:07 +0000556 if (getLexer().is(AsmToken::Percent)) {
Chris Lattner0c2538f2010-01-15 18:51:29 +0000557 SMLoc L;
558 if (ParseRegister(IndexReg, L, L)) return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000559
560 if (getLexer().isNot(AsmToken::RParen)) {
561 // Parse the scale amount:
562 // ::= ',' [scale-expression]
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000563 if (getLexer().isNot(AsmToken::Comma)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000564 Error(Parser.getTok().getLoc(),
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000565 "expected comma in scale expression");
566 return 0;
567 }
Sean Callanana83fd7d2010-01-19 20:27:46 +0000568 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000569
570 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000571 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000572
573 int64_t ScaleVal;
574 if (getParser().ParseAbsoluteExpression(ScaleVal))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000575 return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000576
577 // Validate the scale amount.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000578 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
579 Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
580 return 0;
581 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000582 Scale = (unsigned)ScaleVal;
583 }
584 }
585 } else if (getLexer().isNot(AsmToken::RParen)) {
586 // Otherwise we have the unsupported form of a scale amount without an
587 // index.
Sean Callanan936b0d32010-01-19 21:44:56 +0000588 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000589
590 int64_t Value;
591 if (getParser().ParseAbsoluteExpression(Value))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000592 return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000593
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000594 Error(Loc, "cannot have scale factor without index register");
595 return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000596 }
597 }
598
599 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000600 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000601 Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000602 return 0;
603 }
Sean Callanan936b0d32010-01-19 21:44:56 +0000604 SMLoc MemEnd = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000605 Parser.Lex(); // Eat the ')'.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000606
Chris Lattner015cfb12010-01-15 19:33:43 +0000607 return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
608 MemStart, MemEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000609}
610
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000611bool X86ATTAsmParser::
Benjamin Kramer92d89982010-07-14 22:38:02 +0000612ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000613 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Dan Gohman29790ed2010-05-20 16:16:00 +0000614 // The various flavors of pushf and popf use Requires<In32BitMode> and
615 // Requires<In64BitMode>, but the assembler doesn't yet implement that.
616 // For now, just do a manual check to prevent silent misencoding.
617 if (Is64Bit) {
618 if (Name == "popfl")
619 return Error(NameLoc, "popfl cannot be encoded in 64-bit mode");
620 else if (Name == "pushfl")
621 return Error(NameLoc, "pushfl cannot be encoded in 64-bit mode");
Kevin Enderby76a6b662010-07-13 20:05:41 +0000622 else if (Name == "pusha")
623 return Error(NameLoc, "pusha cannot be encoded in 64-bit mode");
Dan Gohman29790ed2010-05-20 16:16:00 +0000624 } else {
625 if (Name == "popfq")
626 return Error(NameLoc, "popfq cannot be encoded in 32-bit mode");
627 else if (Name == "pushfq")
628 return Error(NameLoc, "pushfq cannot be encoded in 32-bit mode");
629 }
630
Kevin Enderby0de0f3f2010-06-08 23:48:44 +0000631 // The "Jump if rCX Zero" form jcxz is not allowed in 64-bit mode and
632 // the form jrcxz is not allowed in 32-bit mode.
633 if (Is64Bit) {
634 if (Name == "jcxz")
635 return Error(NameLoc, "jcxz cannot be encoded in 64-bit mode");
636 } else {
637 if (Name == "jrcxz")
638 return Error(NameLoc, "jrcxz cannot be encoded in 32-bit mode");
639 }
640
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000641 // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
642 // represent alternative syntaxes in the .td file, without requiring
643 // instruction duplication.
644 StringRef PatchedName = StringSwitch<StringRef>(Name)
645 .Case("sal", "shl")
646 .Case("salb", "shlb")
647 .Case("sall", "shll")
648 .Case("salq", "shlq")
649 .Case("salw", "shlw")
650 .Case("repe", "rep")
651 .Case("repz", "rep")
652 .Case("repnz", "repne")
Dan Gohman29790ed2010-05-20 16:16:00 +0000653 .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
654 .Case("popf", Is64Bit ? "popfq" : "popfl")
Kevin Enderby7e7482c2010-05-21 23:01:38 +0000655 .Case("retl", Is64Bit ? "retl" : "ret")
656 .Case("retq", Is64Bit ? "ret" : "retq")
Daniel Dunbard459e292010-05-22 06:37:33 +0000657 .Case("setz", "sete")
658 .Case("setnz", "setne")
659 .Case("jz", "je")
660 .Case("jnz", "jne")
Kevin Enderby9738f642010-05-27 21:33:19 +0000661 .Case("jc", "jb")
Kevin Enderby0de0f3f2010-06-08 23:48:44 +0000662 // FIXME: in 32-bit mode jcxz requires an AdSize prefix. In 64-bit mode
663 // jecxz requires an AdSize prefix but jecxz does not have a prefix in
664 // 32-bit mode.
Kevin Enderby9738f642010-05-27 21:33:19 +0000665 .Case("jecxz", "jcxz")
Kevin Enderby0de0f3f2010-06-08 23:48:44 +0000666 .Case("jrcxz", "jcxz")
Kevin Enderby9738f642010-05-27 21:33:19 +0000667 .Case("jna", "jbe")
668 .Case("jnae", "jb")
669 .Case("jnb", "jae")
670 .Case("jnbe", "ja")
671 .Case("jnc", "jae")
672 .Case("jng", "jle")
673 .Case("jnge", "jl")
674 .Case("jnl", "jge")
675 .Case("jnle", "jg")
676 .Case("jpe", "jp")
677 .Case("jpo", "jnp")
Kevin Enderbydc71cc72010-05-24 20:32:23 +0000678 .Case("cmovcl", "cmovbl")
679 .Case("cmovcl", "cmovbl")
680 .Case("cmovnal", "cmovbel")
681 .Case("cmovnbl", "cmovael")
682 .Case("cmovnbel", "cmoval")
683 .Case("cmovncl", "cmovael")
684 .Case("cmovngl", "cmovlel")
685 .Case("cmovnl", "cmovgel")
686 .Case("cmovngl", "cmovlel")
687 .Case("cmovngel", "cmovll")
688 .Case("cmovnll", "cmovgel")
689 .Case("cmovnlel", "cmovgl")
690 .Case("cmovnzl", "cmovnel")
691 .Case("cmovzl", "cmovel")
Kevin Enderbyb2922892010-05-28 20:59:10 +0000692 .Case("fwait", "wait")
Kevin Enderby4c71e082010-05-28 21:20:21 +0000693 .Case("movzx", "movzb")
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000694 .Default(Name);
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000695
696 // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
697 const MCExpr *ExtraImmOp = 0;
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000698 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000699 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
700 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000701 bool IsVCMP = PatchedName.startswith("vcmp");
702 unsigned SSECCIdx = IsVCMP ? 4 : 3;
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000703 unsigned SSEComparisonCode = StringSwitch<unsigned>(
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000704 PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
Bruno Cardoso Lopes6c614512010-07-07 22:24:03 +0000705 .Case("eq", 0)
706 .Case("lt", 1)
707 .Case("le", 2)
708 .Case("unord", 3)
709 .Case("neq", 4)
710 .Case("nlt", 5)
711 .Case("nle", 6)
712 .Case("ord", 7)
713 .Case("eq_uq", 8)
714 .Case("nge", 9)
715 .Case("ngt", 0x0A)
716 .Case("false", 0x0B)
717 .Case("neq_oq", 0x0C)
718 .Case("ge", 0x0D)
719 .Case("gt", 0x0E)
720 .Case("true", 0x0F)
721 .Case("eq_os", 0x10)
722 .Case("lt_oq", 0x11)
723 .Case("le_oq", 0x12)
724 .Case("unord_s", 0x13)
725 .Case("neq_us", 0x14)
726 .Case("nlt_uq", 0x15)
727 .Case("nle_uq", 0x16)
728 .Case("ord_s", 0x17)
729 .Case("eq_us", 0x18)
730 .Case("nge_uq", 0x19)
731 .Case("ngt_uq", 0x1A)
732 .Case("false_os", 0x1B)
733 .Case("neq_os", 0x1C)
734 .Case("ge_oq", 0x1D)
735 .Case("gt_oq", 0x1E)
736 .Case("true_us", 0x1F)
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000737 .Default(~0U);
738 if (SSEComparisonCode != ~0U) {
739 ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode,
740 getParser().getContext());
741 if (PatchedName.endswith("ss")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000742 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000743 } else if (PatchedName.endswith("sd")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000744 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000745 } else if (PatchedName.endswith("ps")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000746 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000747 } else {
748 assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000749 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000750 }
751 }
752 }
Bruno Cardoso Lopesea0e05a2010-07-23 18:41:12 +0000753
754 // FIXME: Hack to recognize vpclmul<src1_quadword, src2_quadword>dq
755 if (PatchedName.startswith("vpclmul")) {
756 unsigned CLMULQuadWordSelect = StringSwitch<unsigned>(
757 PatchedName.slice(7, PatchedName.size() - 2))
758 .Case("lqlq", 0x00) // src1[63:0], src2[63:0]
759 .Case("hqlq", 0x01) // src1[127:64], src2[63:0]
760 .Case("lqhq", 0x10) // src1[63:0], src2[127:64]
761 .Case("hqhq", 0x11) // src1[127:64], src2[127:64]
762 .Default(~0U);
763 if (CLMULQuadWordSelect != ~0U) {
764 ExtraImmOp = MCConstantExpr::Create(CLMULQuadWordSelect,
765 getParser().getContext());
766 assert(PatchedName.endswith("dq") && "Unexpected mnemonic!");
767 PatchedName = "vpclmulqdq";
768 }
769 }
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000770 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000771
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000772 if (ExtraImmOp)
773 Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
774
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000775 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbar71527c12009-08-11 05:00:25 +0000776
777 // Parse '*' modifier.
778 if (getLexer().is(AsmToken::Star)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000779 SMLoc Loc = Parser.getTok().getLoc();
Chris Lattner528d00b2010-01-15 19:28:38 +0000780 Operands.push_back(X86Operand::CreateToken("*", Loc));
Sean Callanana83fd7d2010-01-19 20:27:46 +0000781 Parser.Lex(); // Eat the star.
Daniel Dunbar71527c12009-08-11 05:00:25 +0000782 }
783
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000784 // Read the first operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000785 if (X86Operand *Op = ParseOperand())
786 Operands.push_back(Op);
787 else
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000788 return true;
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000789
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000790 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +0000791 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000792
793 // Parse and remember the operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000794 if (X86Operand *Op = ParseOperand())
795 Operands.push_back(Op);
796 else
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000797 return true;
798 }
799 }
800
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000801 // FIXME: Hack to handle recognizing s{hr,ar,hl}? $1.
802 if ((Name.startswith("shr") || Name.startswith("sar") ||
803 Name.startswith("shl")) &&
804 Operands.size() == 3 &&
805 static_cast<X86Operand*>(Operands[1])->isImm() &&
806 isa<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm()) &&
Daniel Dunbarfbd12cc2010-03-20 22:36:38 +0000807 cast<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm())->getValue() == 1) {
808 delete Operands[1];
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000809 Operands.erase(Operands.begin() + 1);
Daniel Dunbarfbd12cc2010-03-20 22:36:38 +0000810 }
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000811
Kevin Enderby492d4f42010-05-25 20:52:34 +0000812 // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
813 // "f{mul*,add*,sub*,div*} $op"
814 if ((Name.startswith("fmul") || Name.startswith("fadd") ||
815 Name.startswith("fsub") || Name.startswith("fdiv")) &&
816 Operands.size() == 3 &&
817 static_cast<X86Operand*>(Operands[2])->isReg() &&
818 static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
819 delete Operands[2];
820 Operands.erase(Operands.begin() + 2);
821 }
822
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000823 return false;
Daniel Dunbar3c2a8932009-07-20 18:55:04 +0000824}
825
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000826bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
827 StringRef IDVal = DirectiveID.getIdentifier();
828 if (IDVal == ".word")
829 return ParseDirectiveWord(2, DirectiveID.getLoc());
830 return true;
831}
832
833/// ParseDirectiveWord
834/// ::= .word [ expression (, expression)* ]
835bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
836 if (getLexer().isNot(AsmToken::EndOfStatement)) {
837 for (;;) {
838 const MCExpr *Value;
839 if (getParser().ParseExpression(Value))
840 return true;
841
Chris Lattnerc35681b2010-01-19 19:46:13 +0000842 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000843
844 if (getLexer().is(AsmToken::EndOfStatement))
845 break;
846
847 // FIXME: Improve diagnostic.
848 if (getLexer().isNot(AsmToken::Comma))
849 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +0000850 Parser.Lex();
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000851 }
852 }
853
Sean Callanana83fd7d2010-01-19 20:27:46 +0000854 Parser.Lex();
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000855 return false;
856}
857
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000858bool
859X86ATTAsmParser::MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*>
860 &Operands,
861 MCInst &Inst) {
862 // First, try a direct match.
863 if (!MatchInstructionImpl(Operands, Inst))
864 return false;
865
866 // Ignore anything which is obviously not a suffix match.
867 if (Operands.size() == 0)
868 return true;
869 X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
870 if (!Op->isToken() || Op->getToken().size() > 15)
871 return true;
872
873 // FIXME: Ideally, we would only attempt suffix matches for things which are
874 // valid prefixes, and we could just infer the right unambiguous
875 // type. However, that requires substantially more matcher support than the
876 // following hack.
877
878 // Change the operand to point to a temporary token.
879 char Tmp[16];
880 StringRef Base = Op->getToken();
881 memcpy(Tmp, Base.data(), Base.size());
882 Op->setTokenValue(StringRef(Tmp, Base.size() + 1));
883
884 // Check for the various suffix matches.
885 Tmp[Base.size()] = 'b';
886 bool MatchB = MatchInstructionImpl(Operands, Inst);
887 Tmp[Base.size()] = 'w';
888 bool MatchW = MatchInstructionImpl(Operands, Inst);
889 Tmp[Base.size()] = 'l';
890 bool MatchL = MatchInstructionImpl(Operands, Inst);
Daniel Dunbar059379a2010-05-12 00:54:20 +0000891 Tmp[Base.size()] = 'q';
892 bool MatchQ = MatchInstructionImpl(Operands, Inst);
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000893
894 // Restore the old token.
895 Op->setTokenValue(Base);
896
897 // If exactly one matched, then we treat that as a successful match (and the
898 // instruction will already have been filled in correctly, since the failing
899 // matches won't have modified it).
Daniel Dunbar059379a2010-05-12 00:54:20 +0000900 if (MatchB + MatchW + MatchL + MatchQ == 3)
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000901 return false;
902
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000903 // Otherwise, the match failed.
904 return true;
905}
906
907
Sean Callanan5051cb82010-01-23 02:43:15 +0000908extern "C" void LLVMInitializeX86AsmLexer();
909
Daniel Dunbar71475772009-07-17 20:42:00 +0000910// Force static initialization.
911extern "C" void LLVMInitializeX86AsmParser() {
Daniel Dunbar63ec0932010-03-18 20:06:02 +0000912 RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
913 RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
Sean Callanan5051cb82010-01-23 02:43:15 +0000914 LLVMInitializeX86AsmLexer();
Daniel Dunbar71475772009-07-17 20:42:00 +0000915}
Daniel Dunbar00331992009-07-29 00:02:19 +0000916
917#include "X86GenAsmMatcher.inc"