blob: bcb70da2f150b88e2c9089e43b4de925e10f777d [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 Dunbar2b11c7d2009-07-20 20:01:54 +000012#include "llvm/ADT/SmallVector.h"
Daniel Dunbar3e0c9792010-02-10 21:19:28 +000013#include "llvm/ADT/StringSwitch.h"
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000014#include "llvm/ADT/Twine.h"
Kevin Enderbyce4bec82009-09-10 20:51:44 +000015#include "llvm/MC/MCStreamer.h"
Daniel Dunbar73da11e2009-08-31 08:08:38 +000016#include "llvm/MC/MCExpr.h"
Daniel Dunbarb6d6aa22009-07-31 02:32:59 +000017#include "llvm/MC/MCInst.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000018#include "llvm/MC/MCParser/MCAsmLexer.h"
19#include "llvm/MC/MCParser/MCAsmParser.h"
20#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000021#include "llvm/Support/SourceMgr.h"
Daniel Dunbar71475772009-07-17 20:42:00 +000022#include "llvm/Target/TargetRegistry.h"
23#include "llvm/Target/TargetAsmParser.h"
24using namespace llvm;
25
26namespace {
Benjamin Kramerb60210e2009-07-31 11:35:26 +000027struct X86Operand;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000028
29class X86ATTAsmParser : public TargetAsmParser {
30 MCAsmParser &Parser;
31
Daniel Dunbar63ec0932010-03-18 20:06:02 +000032protected:
33 unsigned Is64Bit : 1;
34
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000035private:
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000036 MCAsmParser &getParser() const { return Parser; }
37
38 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
39
40 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
41
42 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
43
Chris Lattner0c2538f2010-01-15 18:51:29 +000044 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000045
Chris Lattnera2bbb7c2010-01-15 18:44:13 +000046 X86Operand *ParseOperand();
Chris Lattnerb9270732010-04-17 18:56:34 +000047 X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
Kevin Enderbyce4bec82009-09-10 20:51:44 +000048
49 bool ParseDirectiveWord(unsigned Size, SMLoc L);
50
Daniel Dunbar63ec0932010-03-18 20:06:02 +000051 void InstructionCleanup(MCInst &Inst);
52
Daniel Dunbar00331992009-07-29 00:02:19 +000053 /// @name Auto-generated Match Functions
Daniel Dunbar9b816a12010-05-04 16:12:42 +000054 /// {
Daniel Dunbar00331992009-07-29 00:02:19 +000055
Chris Lattnerf29c0b62010-01-14 22:21:20 +000056 bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbare10787e2009-08-07 08:26:05 +000057 MCInst &Inst);
58
Daniel Dunbar9b816a12010-05-04 16:12:42 +000059 bool MatchInstructionImpl(
60 const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst);
61
Daniel Dunbar00331992009-07-29 00:02:19 +000062 /// }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000063
64public:
65 X86ATTAsmParser(const Target &T, MCAsmParser &_Parser)
66 : TargetAsmParser(T), Parser(_Parser) {}
67
Chris Lattner77fd6772010-01-14 21:32:45 +000068 virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc,
Chris Lattnerf29c0b62010-01-14 22:21:20 +000069 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderbyce4bec82009-09-10 20:51:44 +000070
71 virtual bool ParseDirective(AsmToken DirectiveID);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000072};
Daniel Dunbar63ec0932010-03-18 20:06:02 +000073
74class X86_32ATTAsmParser : public X86ATTAsmParser {
75public:
76 X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser)
77 : X86ATTAsmParser(T, _Parser) {
78 Is64Bit = false;
79 }
80};
81
82class X86_64ATTAsmParser : public X86ATTAsmParser {
83public:
84 X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser)
85 : X86ATTAsmParser(T, _Parser) {
86 Is64Bit = true;
87 }
88};
89
Chris Lattner4eb9df02009-07-29 06:33:53 +000090} // end anonymous namespace
91
Sean Callanan86c11812010-01-23 00:40:33 +000092/// @name Auto-generated Match Functions
93/// {
94
Chris Lattner60db0a62010-02-09 00:34:28 +000095static unsigned MatchRegisterName(StringRef Name);
Sean Callanan86c11812010-01-23 00:40:33 +000096
97/// }
Chris Lattner4eb9df02009-07-29 06:33:53 +000098
99namespace {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000100
101/// X86Operand - Instances of this class represent a parsed X86 machine
102/// instruction.
Chris Lattner872501b2010-01-14 21:20:55 +0000103struct X86Operand : public MCParsedAsmOperand {
Chris Lattner86e61532010-01-15 19:06:59 +0000104 enum KindTy {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000105 Token,
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000106 Register,
107 Immediate,
108 Memory
109 } Kind;
110
Chris Lattner0c2538f2010-01-15 18:51:29 +0000111 SMLoc StartLoc, EndLoc;
112
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000113 union {
114 struct {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000115 const char *Data;
116 unsigned Length;
117 } Tok;
118
119 struct {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000120 unsigned RegNo;
121 } Reg;
122
123 struct {
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000124 const MCExpr *Val;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000125 } Imm;
126
127 struct {
128 unsigned SegReg;
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000129 const MCExpr *Disp;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000130 unsigned BaseReg;
131 unsigned IndexReg;
132 unsigned Scale;
133 } Mem;
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +0000134 };
Daniel Dunbar71475772009-07-17 20:42:00 +0000135
Chris Lattner015cfb12010-01-15 19:33:43 +0000136 X86Operand(KindTy K, SMLoc Start, SMLoc End)
Chris Lattner86e61532010-01-15 19:06:59 +0000137 : Kind(K), StartLoc(Start), EndLoc(End) {}
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000138
Chris Lattner86e61532010-01-15 19:06:59 +0000139 /// getStartLoc - Get the location of the first token of this operand.
140 SMLoc getStartLoc() const { return StartLoc; }
141 /// getEndLoc - Get the location of the last token of this operand.
142 SMLoc getEndLoc() const { return EndLoc; }
143
Daniel Dunbare10787e2009-08-07 08:26:05 +0000144 StringRef getToken() const {
145 assert(Kind == Token && "Invalid access!");
146 return StringRef(Tok.Data, Tok.Length);
147 }
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000148 void setTokenValue(StringRef Value) {
149 assert(Kind == Token && "Invalid access!");
150 Tok.Data = Value.data();
151 Tok.Length = Value.size();
152 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000153
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000154 unsigned getReg() const {
155 assert(Kind == Register && "Invalid access!");
156 return Reg.RegNo;
157 }
Daniel Dunbarf59ee962009-07-28 20:47:52 +0000158
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000159 const MCExpr *getImm() const {
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000160 assert(Kind == Immediate && "Invalid access!");
161 return Imm.Val;
162 }
163
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000164 const MCExpr *getMemDisp() const {
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000165 assert(Kind == Memory && "Invalid access!");
166 return Mem.Disp;
167 }
168 unsigned getMemSegReg() const {
169 assert(Kind == Memory && "Invalid access!");
170 return Mem.SegReg;
171 }
172 unsigned getMemBaseReg() const {
173 assert(Kind == Memory && "Invalid access!");
174 return Mem.BaseReg;
175 }
176 unsigned getMemIndexReg() const {
177 assert(Kind == Memory && "Invalid access!");
178 return Mem.IndexReg;
179 }
180 unsigned getMemScale() const {
181 assert(Kind == Memory && "Invalid access!");
182 return Mem.Scale;
183 }
184
Daniel Dunbar541efcc2009-08-08 07:50:56 +0000185 bool isToken() const {return Kind == Token; }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000186
187 bool isImm() const { return Kind == Immediate; }
188
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000189 bool isImmSExti16i8() const {
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000190 if (!isImm())
191 return false;
192
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000193 // If this isn't a constant expr, just assume it fits and let relaxation
194 // handle it.
195 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
196 if (!CE)
197 return true;
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000198
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000199 // Otherwise, check the value is in a range that makes sense for this
200 // extension.
201 uint64_t Value = CE->getValue();
202 return (( Value <= 0x000000000000007FULL)||
203 (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)||
204 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000205 }
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000206 bool isImmSExti32i8() const {
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000207 if (!isImm())
208 return false;
209
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000210 // If this isn't a constant expr, just assume it fits and let relaxation
211 // handle it.
212 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
213 if (!CE)
214 return true;
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000215
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000216 // Otherwise, check the value is in a range that makes sense for this
217 // extension.
218 uint64_t Value = CE->getValue();
219 return (( Value <= 0x000000000000007FULL)||
220 (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
221 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
222 }
223 bool isImmSExti64i8() const {
224 if (!isImm())
225 return false;
226
227 // If this isn't a constant expr, just assume it fits and let relaxation
228 // handle it.
229 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
230 if (!CE)
231 return true;
232
233 // Otherwise, check the value is in a range that makes sense for this
234 // extension.
235 uint64_t Value = CE->getValue();
236 return (( Value <= 0x000000000000007FULL)||
237 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
238 }
239 bool isImmSExti64i32() const {
240 if (!isImm())
241 return false;
242
243 // If this isn't a constant expr, just assume it fits and let relaxation
244 // handle it.
245 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
246 if (!CE)
247 return true;
248
249 // Otherwise, check the value is in a range that makes sense for this
250 // extension.
251 uint64_t Value = CE->getValue();
252 return (( Value <= 0x000000007FFFFFFFULL)||
253 (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000254 }
255
Daniel Dunbare10787e2009-08-07 08:26:05 +0000256 bool isMem() const { return Kind == Memory; }
257
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000258 bool isAbsMem() const {
259 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
Daniel Dunbar3184f222010-02-02 21:44:16 +0000260 !getMemIndexReg() && getMemScale() == 1;
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000261 }
262
Daniel Dunbara97adee2010-01-30 00:24:00 +0000263 bool isNoSegMem() const {
264 return Kind == Memory && !getMemSegReg();
265 }
266
Daniel Dunbare10787e2009-08-07 08:26:05 +0000267 bool isReg() const { return Kind == Register; }
268
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000269 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
270 // Add as immediates when possible.
271 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
272 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
273 else
274 Inst.addOperand(MCOperand::CreateExpr(Expr));
275 }
276
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000277 void addRegOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000278 assert(N == 1 && "Invalid number of operands!");
279 Inst.addOperand(MCOperand::CreateReg(getReg()));
280 }
281
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000282 void addImmOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000283 assert(N == 1 && "Invalid number of operands!");
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000284 addExpr(Inst, getImm());
Daniel Dunbare10787e2009-08-07 08:26:05 +0000285 }
286
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000287 void addMemOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbara97adee2010-01-30 00:24:00 +0000288 assert((N == 5) && "Invalid number of operands!");
Daniel Dunbare10787e2009-08-07 08:26:05 +0000289 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
290 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
291 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000292 addExpr(Inst, getMemDisp());
Daniel Dunbara97adee2010-01-30 00:24:00 +0000293 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
294 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000295
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000296 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
297 assert((N == 1) && "Invalid number of operands!");
298 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
299 }
300
Daniel Dunbara97adee2010-01-30 00:24:00 +0000301 void addNoSegMemOperands(MCInst &Inst, unsigned N) const {
302 assert((N == 4) && "Invalid number of operands!");
Daniel Dunbara97adee2010-01-30 00:24:00 +0000303 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
304 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
305 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000306 addExpr(Inst, getMemDisp());
Daniel Dunbare10787e2009-08-07 08:26:05 +0000307 }
308
Chris Lattner528d00b2010-01-15 19:28:38 +0000309 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
310 X86Operand *Res = new X86Operand(Token, Loc, Loc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000311 Res->Tok.Data = Str.data();
312 Res->Tok.Length = Str.size();
Daniel Dunbare10787e2009-08-07 08:26:05 +0000313 return Res;
314 }
315
Chris Lattner0c2538f2010-01-15 18:51:29 +0000316 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
Chris Lattner86e61532010-01-15 19:06:59 +0000317 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000318 Res->Reg.RegNo = RegNo;
Chris Lattner0c2538f2010-01-15 18:51:29 +0000319 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000320 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000321
Chris Lattner528d00b2010-01-15 19:28:38 +0000322 static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
323 X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000324 Res->Imm.Val = Val;
325 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000326 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000327
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000328 /// Create an absolute memory operand.
329 static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
330 SMLoc EndLoc) {
331 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
332 Res->Mem.SegReg = 0;
333 Res->Mem.Disp = Disp;
334 Res->Mem.BaseReg = 0;
335 Res->Mem.IndexReg = 0;
Daniel Dunbar3184f222010-02-02 21:44:16 +0000336 Res->Mem.Scale = 1;
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000337 return Res;
338 }
339
340 /// Create a generalized memory operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000341 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
342 unsigned BaseReg, unsigned IndexReg,
Chris Lattner015cfb12010-01-15 19:33:43 +0000343 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000344 // We should never just have a displacement, that should be parsed as an
345 // absolute memory operand.
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000346 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
347
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000348 // The scale should always be one of {1,2,4,8}.
349 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000350 "Invalid scale!");
Chris Lattner015cfb12010-01-15 19:33:43 +0000351 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000352 Res->Mem.SegReg = SegReg;
353 Res->Mem.Disp = Disp;
354 Res->Mem.BaseReg = BaseReg;
355 Res->Mem.IndexReg = IndexReg;
356 Res->Mem.Scale = Scale;
357 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000358 }
359};
Daniel Dunbar3c2a8932009-07-20 18:55:04 +0000360
Chris Lattner4eb9df02009-07-29 06:33:53 +0000361} // end anonymous namespace.
Daniel Dunbarf59ee962009-07-28 20:47:52 +0000362
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000363
Chris Lattner0c2538f2010-01-15 18:51:29 +0000364bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
365 SMLoc &StartLoc, SMLoc &EndLoc) {
Chris Lattnercc2ad082010-01-15 18:27:19 +0000366 RegNo = 0;
Sean Callanan936b0d32010-01-19 21:44:56 +0000367 const AsmToken &TokPercent = Parser.getTok();
Kevin Enderby7d912182009-09-03 17:15:07 +0000368 assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
Chris Lattner0c2538f2010-01-15 18:51:29 +0000369 StartLoc = TokPercent.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000370 Parser.Lex(); // Eat percent token.
Kevin Enderby7d912182009-09-03 17:15:07 +0000371
Sean Callanan936b0d32010-01-19 21:44:56 +0000372 const AsmToken &Tok = Parser.getTok();
Kevin Enderbyc0edda32009-09-16 17:18:29 +0000373 if (Tok.isNot(AsmToken::Identifier))
374 return Error(Tok.getLoc(), "invalid register name");
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000375
Daniel Dunbar00331992009-07-29 00:02:19 +0000376 // FIXME: Validate register for the current architecture; we have to do
377 // validation later, so maybe there is no need for this here.
Kevin Enderby7d912182009-09-03 17:15:07 +0000378 RegNo = MatchRegisterName(Tok.getString());
Chris Lattner60db0a62010-02-09 00:34:28 +0000379
Chris Lattnerd00faaa2010-02-09 00:49:22 +0000380 // Parse %st(1) and "%st" as "%st(0)"
381 if (RegNo == 0 && Tok.getString() == "st") {
382 RegNo = X86::ST0;
383 EndLoc = Tok.getLoc();
384 Parser.Lex(); // Eat 'st'
385
386 // Check to see if we have '(4)' after %st.
387 if (getLexer().isNot(AsmToken::LParen))
388 return false;
389 // Lex the paren.
390 getParser().Lex();
391
392 const AsmToken &IntTok = Parser.getTok();
393 if (IntTok.isNot(AsmToken::Integer))
394 return Error(IntTok.getLoc(), "expected stack index");
395 switch (IntTok.getIntVal()) {
396 case 0: RegNo = X86::ST0; break;
397 case 1: RegNo = X86::ST1; break;
398 case 2: RegNo = X86::ST2; break;
399 case 3: RegNo = X86::ST3; break;
400 case 4: RegNo = X86::ST4; break;
401 case 5: RegNo = X86::ST5; break;
402 case 6: RegNo = X86::ST6; break;
403 case 7: RegNo = X86::ST7; break;
404 default: return Error(IntTok.getLoc(), "invalid stack index");
405 }
406
407 if (getParser().Lex().isNot(AsmToken::RParen))
408 return Error(Parser.getTok().getLoc(), "expected ')'");
409
410 EndLoc = Tok.getLoc();
411 Parser.Lex(); // Eat ')'
412 return false;
413 }
414
Daniel Dunbar66f4f542009-08-08 21:22:41 +0000415 if (RegNo == 0)
Daniel Dunbar00331992009-07-29 00:02:19 +0000416 return Error(Tok.getLoc(), "invalid register name");
417
Chris Lattner0c2538f2010-01-15 18:51:29 +0000418 EndLoc = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000419 Parser.Lex(); // Eat identifier token.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000420 return false;
Daniel Dunbar71475772009-07-17 20:42:00 +0000421}
422
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000423X86Operand *X86ATTAsmParser::ParseOperand() {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000424 switch (getLexer().getKind()) {
425 default:
Chris Lattnerb9270732010-04-17 18:56:34 +0000426 // Parse a memory operand with no segment register.
427 return ParseMemOperand(0, Parser.getTok().getLoc());
Chris Lattnercc2ad082010-01-15 18:27:19 +0000428 case AsmToken::Percent: {
Chris Lattnerb9270732010-04-17 18:56:34 +0000429 // Read the register.
Chris Lattnercc2ad082010-01-15 18:27:19 +0000430 unsigned RegNo;
Chris Lattner0c2538f2010-01-15 18:51:29 +0000431 SMLoc Start, End;
432 if (ParseRegister(RegNo, Start, End)) return 0;
Chris Lattnerb9270732010-04-17 18:56:34 +0000433
434 // If this is a segment register followed by a ':', then this is the start
435 // of a memory reference, otherwise this is a normal register reference.
436 if (getLexer().isNot(AsmToken::Colon))
437 return X86Operand::CreateReg(RegNo, Start, End);
438
439
440 getParser().Lex(); // Eat the colon.
441 return ParseMemOperand(RegNo, Start);
Chris Lattnercc2ad082010-01-15 18:27:19 +0000442 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000443 case AsmToken::Dollar: {
444 // $42 -> immediate.
Sean Callanan936b0d32010-01-19 21:44:56 +0000445 SMLoc Start = Parser.getTok().getLoc(), End;
Sean Callanana83fd7d2010-01-19 20:27:46 +0000446 Parser.Lex();
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000447 const MCExpr *Val;
Chris Lattnere17df0b2010-01-15 19:39:23 +0000448 if (getParser().ParseExpression(Val, End))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000449 return 0;
Chris Lattner528d00b2010-01-15 19:28:38 +0000450 return X86Operand::CreateImm(Val, Start, End);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000451 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000452 }
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +0000453}
454
Chris Lattnerb9270732010-04-17 18:56:34 +0000455/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
456/// has already been parsed if present.
457X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
458
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000459 // We have to disambiguate a parenthesized expression "(4+5)" from the start
460 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
Chris Lattner807a3bc2010-01-24 01:07:33 +0000461 // only way to do this without lookahead is to eat the '(' and see what is
462 // after it.
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000463 const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000464 if (getLexer().isNot(AsmToken::LParen)) {
Chris Lattnere17df0b2010-01-15 19:39:23 +0000465 SMLoc ExprEnd;
466 if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000467
468 // After parsing the base expression we could either have a parenthesized
469 // memory address or not. If not, return now. If so, eat the (.
470 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000471 // Unless we have a segment register, treat this as an immediate.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000472 if (SegReg == 0)
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000473 return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
Chris Lattner015cfb12010-01-15 19:33:43 +0000474 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000475 }
476
477 // Eat the '('.
Sean Callanana83fd7d2010-01-19 20:27:46 +0000478 Parser.Lex();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000479 } else {
480 // Okay, we have a '('. We don't know if this is an expression or not, but
481 // so we have to eat the ( to see beyond it.
Sean Callanan936b0d32010-01-19 21:44:56 +0000482 SMLoc LParenLoc = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000483 Parser.Lex(); // Eat the '('.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000484
Kevin Enderby7d912182009-09-03 17:15:07 +0000485 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000486 // Nothing to do here, fall into the code below with the '(' part of the
487 // memory operand consumed.
488 } else {
Chris Lattner528d00b2010-01-15 19:28:38 +0000489 SMLoc ExprEnd;
490
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000491 // It must be an parenthesized expression, parse it now.
Chris Lattner528d00b2010-01-15 19:28:38 +0000492 if (getParser().ParseParenExpression(Disp, ExprEnd))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000493 return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000494
495 // After parsing the base expression we could either have a parenthesized
496 // memory address or not. If not, return now. If so, eat the (.
497 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000498 // Unless we have a segment register, treat this as an immediate.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000499 if (SegReg == 0)
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000500 return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
Chris Lattner015cfb12010-01-15 19:33:43 +0000501 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000502 }
503
504 // Eat the '('.
Sean Callanana83fd7d2010-01-19 20:27:46 +0000505 Parser.Lex();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000506 }
507 }
508
509 // If we reached here, then we just ate the ( of the memory operand. Process
510 // the rest of the memory operand.
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000511 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000512
Chris Lattner0c2538f2010-01-15 18:51:29 +0000513 if (getLexer().is(AsmToken::Percent)) {
514 SMLoc L;
515 if (ParseRegister(BaseReg, L, L)) return 0;
516 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000517
518 if (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +0000519 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000520
521 // Following the comma we should have either an index register, or a scale
522 // value. We don't support the later form, but we want to parse it
523 // correctly.
524 //
525 // Not that even though it would be completely consistent to support syntax
526 // like "1(%eax,,1)", the assembler doesn't.
Kevin Enderby7d912182009-09-03 17:15:07 +0000527 if (getLexer().is(AsmToken::Percent)) {
Chris Lattner0c2538f2010-01-15 18:51:29 +0000528 SMLoc L;
529 if (ParseRegister(IndexReg, L, L)) return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000530
531 if (getLexer().isNot(AsmToken::RParen)) {
532 // Parse the scale amount:
533 // ::= ',' [scale-expression]
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000534 if (getLexer().isNot(AsmToken::Comma)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000535 Error(Parser.getTok().getLoc(),
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000536 "expected comma in scale expression");
537 return 0;
538 }
Sean Callanana83fd7d2010-01-19 20:27:46 +0000539 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000540
541 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000542 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000543
544 int64_t ScaleVal;
545 if (getParser().ParseAbsoluteExpression(ScaleVal))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000546 return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000547
548 // Validate the scale amount.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000549 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
550 Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
551 return 0;
552 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000553 Scale = (unsigned)ScaleVal;
554 }
555 }
556 } else if (getLexer().isNot(AsmToken::RParen)) {
557 // Otherwise we have the unsupported form of a scale amount without an
558 // index.
Sean Callanan936b0d32010-01-19 21:44:56 +0000559 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000560
561 int64_t Value;
562 if (getParser().ParseAbsoluteExpression(Value))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000563 return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000564
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000565 Error(Loc, "cannot have scale factor without index register");
566 return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000567 }
568 }
569
570 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000571 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000572 Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000573 return 0;
574 }
Sean Callanan936b0d32010-01-19 21:44:56 +0000575 SMLoc MemEnd = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000576 Parser.Lex(); // Eat the ')'.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000577
Chris Lattner015cfb12010-01-15 19:33:43 +0000578 return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
579 MemStart, MemEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000580}
581
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000582bool X86ATTAsmParser::
583ParseInstruction(const StringRef &Name, SMLoc NameLoc,
584 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Dan Gohman29790ed2010-05-20 16:16:00 +0000585 // The various flavors of pushf and popf use Requires<In32BitMode> and
586 // Requires<In64BitMode>, but the assembler doesn't yet implement that.
587 // For now, just do a manual check to prevent silent misencoding.
588 if (Is64Bit) {
589 if (Name == "popfl")
590 return Error(NameLoc, "popfl cannot be encoded in 64-bit mode");
591 else if (Name == "pushfl")
592 return Error(NameLoc, "pushfl cannot be encoded in 64-bit mode");
593 } else {
594 if (Name == "popfq")
595 return Error(NameLoc, "popfq cannot be encoded in 32-bit mode");
596 else if (Name == "pushfq")
597 return Error(NameLoc, "pushfq cannot be encoded in 32-bit mode");
598 }
599
Kevin Enderby0de0f3f2010-06-08 23:48:44 +0000600 // The "Jump if rCX Zero" form jcxz is not allowed in 64-bit mode and
601 // the form jrcxz is not allowed in 32-bit mode.
602 if (Is64Bit) {
603 if (Name == "jcxz")
604 return Error(NameLoc, "jcxz cannot be encoded in 64-bit mode");
605 } else {
606 if (Name == "jrcxz")
607 return Error(NameLoc, "jrcxz cannot be encoded in 32-bit mode");
608 }
609
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000610 // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
611 // represent alternative syntaxes in the .td file, without requiring
612 // instruction duplication.
613 StringRef PatchedName = StringSwitch<StringRef>(Name)
614 .Case("sal", "shl")
615 .Case("salb", "shlb")
616 .Case("sall", "shll")
617 .Case("salq", "shlq")
618 .Case("salw", "shlw")
619 .Case("repe", "rep")
620 .Case("repz", "rep")
621 .Case("repnz", "repne")
Dan Gohman29790ed2010-05-20 16:16:00 +0000622 .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
623 .Case("popf", Is64Bit ? "popfq" : "popfl")
Kevin Enderby7e7482c2010-05-21 23:01:38 +0000624 .Case("retl", Is64Bit ? "retl" : "ret")
625 .Case("retq", Is64Bit ? "ret" : "retq")
Daniel Dunbard459e292010-05-22 06:37:33 +0000626 .Case("setz", "sete")
627 .Case("setnz", "setne")
628 .Case("jz", "je")
629 .Case("jnz", "jne")
Kevin Enderby9738f642010-05-27 21:33:19 +0000630 .Case("jc", "jb")
Kevin Enderby0de0f3f2010-06-08 23:48:44 +0000631 // FIXME: in 32-bit mode jcxz requires an AdSize prefix. In 64-bit mode
632 // jecxz requires an AdSize prefix but jecxz does not have a prefix in
633 // 32-bit mode.
Kevin Enderby9738f642010-05-27 21:33:19 +0000634 .Case("jecxz", "jcxz")
Kevin Enderby0de0f3f2010-06-08 23:48:44 +0000635 .Case("jrcxz", "jcxz")
Kevin Enderby9738f642010-05-27 21:33:19 +0000636 .Case("jna", "jbe")
637 .Case("jnae", "jb")
638 .Case("jnb", "jae")
639 .Case("jnbe", "ja")
640 .Case("jnc", "jae")
641 .Case("jng", "jle")
642 .Case("jnge", "jl")
643 .Case("jnl", "jge")
644 .Case("jnle", "jg")
645 .Case("jpe", "jp")
646 .Case("jpo", "jnp")
Kevin Enderbydc71cc72010-05-24 20:32:23 +0000647 .Case("cmovcl", "cmovbl")
648 .Case("cmovcl", "cmovbl")
649 .Case("cmovnal", "cmovbel")
650 .Case("cmovnbl", "cmovael")
651 .Case("cmovnbel", "cmoval")
652 .Case("cmovncl", "cmovael")
653 .Case("cmovngl", "cmovlel")
654 .Case("cmovnl", "cmovgel")
655 .Case("cmovngl", "cmovlel")
656 .Case("cmovngel", "cmovll")
657 .Case("cmovnll", "cmovgel")
658 .Case("cmovnlel", "cmovgl")
659 .Case("cmovnzl", "cmovnel")
660 .Case("cmovzl", "cmovel")
Kevin Enderbyb2922892010-05-28 20:59:10 +0000661 .Case("fwait", "wait")
Kevin Enderby4c71e082010-05-28 21:20:21 +0000662 .Case("movzx", "movzb")
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000663 .Default(Name);
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000664
665 // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
666 const MCExpr *ExtraImmOp = 0;
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000667 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000668 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
669 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000670 bool IsVCMP = PatchedName.startswith("vcmp");
671 unsigned SSECCIdx = IsVCMP ? 4 : 3;
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000672 unsigned SSEComparisonCode = StringSwitch<unsigned>(
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000673 PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000674 .Case("eq", 0)
675 .Case("lt", 1)
676 .Case("le", 2)
677 .Case("unord", 3)
678 .Case("neq", 4)
679 .Case("nlt", 5)
680 .Case("nle", 6)
681 .Case("ord", 7)
682 .Default(~0U);
683 if (SSEComparisonCode != ~0U) {
684 ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode,
685 getParser().getContext());
686 if (PatchedName.endswith("ss")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000687 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000688 } else if (PatchedName.endswith("sd")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000689 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000690 } else if (PatchedName.endswith("ps")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000691 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000692 } else {
693 assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000694 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000695 }
696 }
697 }
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000698 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000699
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000700 if (ExtraImmOp)
701 Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
702
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000703 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbar71527c12009-08-11 05:00:25 +0000704
705 // Parse '*' modifier.
706 if (getLexer().is(AsmToken::Star)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000707 SMLoc Loc = Parser.getTok().getLoc();
Chris Lattner528d00b2010-01-15 19:28:38 +0000708 Operands.push_back(X86Operand::CreateToken("*", Loc));
Sean Callanana83fd7d2010-01-19 20:27:46 +0000709 Parser.Lex(); // Eat the star.
Daniel Dunbar71527c12009-08-11 05:00:25 +0000710 }
711
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000712 // Read the first operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000713 if (X86Operand *Op = ParseOperand())
714 Operands.push_back(Op);
715 else
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000716 return true;
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000717
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000718 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +0000719 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000720
721 // Parse and remember the operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000722 if (X86Operand *Op = ParseOperand())
723 Operands.push_back(Op);
724 else
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000725 return true;
726 }
727 }
728
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000729 // FIXME: Hack to handle recognizing s{hr,ar,hl}? $1.
730 if ((Name.startswith("shr") || Name.startswith("sar") ||
731 Name.startswith("shl")) &&
732 Operands.size() == 3 &&
733 static_cast<X86Operand*>(Operands[1])->isImm() &&
734 isa<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm()) &&
Daniel Dunbarfbd12cc2010-03-20 22:36:38 +0000735 cast<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm())->getValue() == 1) {
736 delete Operands[1];
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000737 Operands.erase(Operands.begin() + 1);
Daniel Dunbarfbd12cc2010-03-20 22:36:38 +0000738 }
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000739
Kevin Enderby492d4f42010-05-25 20:52:34 +0000740 // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
741 // "f{mul*,add*,sub*,div*} $op"
742 if ((Name.startswith("fmul") || Name.startswith("fadd") ||
743 Name.startswith("fsub") || Name.startswith("fdiv")) &&
744 Operands.size() == 3 &&
745 static_cast<X86Operand*>(Operands[2])->isReg() &&
746 static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
747 delete Operands[2];
748 Operands.erase(Operands.begin() + 2);
749 }
750
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000751 return false;
Daniel Dunbar3c2a8932009-07-20 18:55:04 +0000752}
753
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000754bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
755 StringRef IDVal = DirectiveID.getIdentifier();
756 if (IDVal == ".word")
757 return ParseDirectiveWord(2, DirectiveID.getLoc());
758 return true;
759}
760
761/// ParseDirectiveWord
762/// ::= .word [ expression (, expression)* ]
763bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
764 if (getLexer().isNot(AsmToken::EndOfStatement)) {
765 for (;;) {
766 const MCExpr *Value;
767 if (getParser().ParseExpression(Value))
768 return true;
769
Chris Lattnerc35681b2010-01-19 19:46:13 +0000770 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000771
772 if (getLexer().is(AsmToken::EndOfStatement))
773 break;
774
775 // FIXME: Improve diagnostic.
776 if (getLexer().isNot(AsmToken::Comma))
777 return Error(L, "unexpected token in directive");
Sean Callanana83fd7d2010-01-19 20:27:46 +0000778 Parser.Lex();
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000779 }
780 }
781
Sean Callanana83fd7d2010-01-19 20:27:46 +0000782 Parser.Lex();
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000783 return false;
784}
785
Chris Lattner9efef002010-05-13 00:02:47 +0000786/// LowerMOffset - Lower an 'moffset' form of an instruction, which just has a
787/// imm operand, to having "rm" or "mr" operands with the offset in the disp
788/// field.
789static void LowerMOffset(MCInst &Inst, unsigned Opc, unsigned RegNo,
790 bool isMR) {
791 MCOperand Disp = Inst.getOperand(0);
792
793 // Start over with an empty instruction.
794 Inst = MCInst();
795 Inst.setOpcode(Opc);
796
797 if (!isMR)
798 Inst.addOperand(MCOperand::CreateReg(RegNo));
799
800 // Add the mem operand.
801 Inst.addOperand(MCOperand::CreateReg(0)); // Segment
802 Inst.addOperand(MCOperand::CreateImm(1)); // Scale
803 Inst.addOperand(MCOperand::CreateReg(0)); // IndexReg
804 Inst.addOperand(Disp); // Displacement
805 Inst.addOperand(MCOperand::CreateReg(0)); // BaseReg
806
807 if (isMR)
808 Inst.addOperand(MCOperand::CreateReg(RegNo));
809}
810
Daniel Dunbar63ec0932010-03-18 20:06:02 +0000811// FIXME: Custom X86 cleanup function to implement a temporary hack to handle
812// matching INCL/DECL correctly for x86_64. This needs to be replaced by a
813// proper mechanism for supporting (ambiguous) feature dependent instructions.
814void X86ATTAsmParser::InstructionCleanup(MCInst &Inst) {
815 if (!Is64Bit) return;
816
817 switch (Inst.getOpcode()) {
818 case X86::DEC16r: Inst.setOpcode(X86::DEC64_16r); break;
819 case X86::DEC16m: Inst.setOpcode(X86::DEC64_16m); break;
820 case X86::DEC32r: Inst.setOpcode(X86::DEC64_32r); break;
821 case X86::DEC32m: Inst.setOpcode(X86::DEC64_32m); break;
822 case X86::INC16r: Inst.setOpcode(X86::INC64_16r); break;
823 case X86::INC16m: Inst.setOpcode(X86::INC64_16m); break;
824 case X86::INC32r: Inst.setOpcode(X86::INC64_32r); break;
825 case X86::INC32m: Inst.setOpcode(X86::INC64_32m); break;
Chris Lattner9efef002010-05-13 00:02:47 +0000826
827 // moffset instructions are x86-32 only.
828 case X86::MOV8o8a: LowerMOffset(Inst, X86::MOV8rm , X86::AL , false); break;
829 case X86::MOV16o16a: LowerMOffset(Inst, X86::MOV16rm, X86::AX , false); break;
830 case X86::MOV32o32a: LowerMOffset(Inst, X86::MOV32rm, X86::EAX, false); break;
831 case X86::MOV8ao8: LowerMOffset(Inst, X86::MOV8mr , X86::AL , true); break;
832 case X86::MOV16ao16: LowerMOffset(Inst, X86::MOV16mr, X86::AX , true); break;
833 case X86::MOV32ao32: LowerMOffset(Inst, X86::MOV32mr, X86::EAX, true); break;
Daniel Dunbar63ec0932010-03-18 20:06:02 +0000834 }
835}
836
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000837bool
838X86ATTAsmParser::MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*>
839 &Operands,
840 MCInst &Inst) {
841 // First, try a direct match.
842 if (!MatchInstructionImpl(Operands, Inst))
843 return false;
844
845 // Ignore anything which is obviously not a suffix match.
846 if (Operands.size() == 0)
847 return true;
848 X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
849 if (!Op->isToken() || Op->getToken().size() > 15)
850 return true;
851
852 // FIXME: Ideally, we would only attempt suffix matches for things which are
853 // valid prefixes, and we could just infer the right unambiguous
854 // type. However, that requires substantially more matcher support than the
855 // following hack.
856
857 // Change the operand to point to a temporary token.
858 char Tmp[16];
859 StringRef Base = Op->getToken();
860 memcpy(Tmp, Base.data(), Base.size());
861 Op->setTokenValue(StringRef(Tmp, Base.size() + 1));
862
863 // Check for the various suffix matches.
864 Tmp[Base.size()] = 'b';
865 bool MatchB = MatchInstructionImpl(Operands, Inst);
866 Tmp[Base.size()] = 'w';
867 bool MatchW = MatchInstructionImpl(Operands, Inst);
868 Tmp[Base.size()] = 'l';
869 bool MatchL = MatchInstructionImpl(Operands, Inst);
Daniel Dunbar059379a2010-05-12 00:54:20 +0000870 Tmp[Base.size()] = 'q';
871 bool MatchQ = MatchInstructionImpl(Operands, Inst);
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000872
873 // Restore the old token.
874 Op->setTokenValue(Base);
875
876 // If exactly one matched, then we treat that as a successful match (and the
877 // instruction will already have been filled in correctly, since the failing
878 // matches won't have modified it).
Daniel Dunbar059379a2010-05-12 00:54:20 +0000879 if (MatchB + MatchW + MatchL + MatchQ == 3)
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000880 return false;
881
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000882 // Otherwise, the match failed.
883 return true;
884}
885
886
Sean Callanan5051cb82010-01-23 02:43:15 +0000887extern "C" void LLVMInitializeX86AsmLexer();
888
Daniel Dunbar71475772009-07-17 20:42:00 +0000889// Force static initialization.
890extern "C" void LLVMInitializeX86AsmParser() {
Daniel Dunbar63ec0932010-03-18 20:06:02 +0000891 RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
892 RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
Sean Callanan5051cb82010-01-23 02:43:15 +0000893 LLVMInitializeX86AsmLexer();
Daniel Dunbar71475772009-07-17 20:42:00 +0000894}
Daniel Dunbar00331992009-07-29 00:02:19 +0000895
896#include "X86GenAsmMatcher.inc"