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