blob: 9b1ef19742990571765c623bab32ad936f0d3d16 [file] [log] [blame]
Daniel Dunbar092a9dd2009-07-17 20:42:00 +00001//===-- X86AsmParser.cpp - Parse X86 assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner98986712010-01-14 22:21:20 +000010#include "llvm/Target/TargetAsmParser.h"
Daniel Dunbar4cb1e132009-07-18 23:03:22 +000011#include "X86.h"
Daniel Dunbardbd692a2009-07-20 20:01:54 +000012#include "llvm/ADT/SmallVector.h"
Daniel Dunbar1b6c0602010-02-10 21:19:28 +000013#include "llvm/ADT/StringSwitch.h"
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000014#include "llvm/ADT/Twine.h"
Kevin Enderby9c656452009-09-10 20:51:44 +000015#include "llvm/MC/MCStreamer.h"
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +000016#include "llvm/MC/MCExpr.h"
Daniel Dunbara027d222009-07-31 02:32:59 +000017#include "llvm/MC/MCInst.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000018#include "llvm/MC/MCParser/MCAsmLexer.h"
19#include "llvm/MC/MCParser/MCAsmParser.h"
20#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000021#include "llvm/Support/SourceMgr.h"
Daniel Dunbar092a9dd2009-07-17 20:42:00 +000022#include "llvm/Target/TargetRegistry.h"
23#include "llvm/Target/TargetAsmParser.h"
24using namespace llvm;
25
26namespace {
Benjamin Kramerc6b79ac2009-07-31 11:35:26 +000027struct X86Operand;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000028
29class X86ATTAsmParser : public TargetAsmParser {
30 MCAsmParser &Parser;
Daniel Dunbard73ada72010-07-19 00:33:49 +000031 TargetMachine &TM;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000032
Daniel Dunbarf98bc632010-03-18 20:06:02 +000033protected:
34 unsigned Is64Bit : 1;
35
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000036private:
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000037 MCAsmParser &getParser() const { return Parser; }
38
39 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
40
41 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
42
43 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
44
Chris Lattner29ef9a22010-01-15 18:51:29 +000045 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000046
Chris Lattner309264d2010-01-15 18:44:13 +000047 X86Operand *ParseOperand();
Chris Lattnereef6d782010-04-17 18:56:34 +000048 X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
Kevin Enderby9c656452009-09-10 20:51:44 +000049
50 bool ParseDirectiveWord(unsigned Size, SMLoc L);
51
Daniel Dunbarf98bc632010-03-18 20:06:02 +000052 void InstructionCleanup(MCInst &Inst);
53
Daniel Dunbar0e2771f2009-07-29 00:02:19 +000054 /// @name Auto-generated Match Functions
Daniel Dunbarc918d602010-05-04 16:12:42 +000055 /// {
Daniel Dunbar0e2771f2009-07-29 00:02:19 +000056
Chris Lattner98986712010-01-14 22:21:20 +000057 bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbar20927f22009-08-07 08:26:05 +000058 MCInst &Inst);
59
Daniel Dunbarc918d602010-05-04 16:12:42 +000060 bool MatchInstructionImpl(
61 const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst);
62
Daniel Dunbar0e2771f2009-07-29 00:02:19 +000063 /// }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000064
65public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000066 X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
67 : TargetAsmParser(T), Parser(_Parser), TM(TM) {}
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000068
Benjamin Kramer38e59892010-07-14 22:38:02 +000069 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +000070 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderby9c656452009-09-10 20:51:44 +000071
72 virtual bool ParseDirective(AsmToken DirectiveID);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000073};
Daniel Dunbarf98bc632010-03-18 20:06:02 +000074
75class X86_32ATTAsmParser : public X86ATTAsmParser {
76public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000077 X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
78 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbarf98bc632010-03-18 20:06:02 +000079 Is64Bit = false;
80 }
81};
82
83class X86_64ATTAsmParser : public X86ATTAsmParser {
84public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000085 X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
86 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbarf98bc632010-03-18 20:06:02 +000087 Is64Bit = true;
88 }
89};
90
Chris Lattner37dfdec2009-07-29 06:33:53 +000091} // end anonymous namespace
92
Sean Callanane9b466d2010-01-23 00:40:33 +000093/// @name Auto-generated Match Functions
94/// {
95
Chris Lattnerb8d6e982010-02-09 00:34:28 +000096static unsigned MatchRegisterName(StringRef Name);
Sean Callanane9b466d2010-01-23 00:40:33 +000097
98/// }
Chris Lattner37dfdec2009-07-29 06:33:53 +000099
100namespace {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000101
102/// X86Operand - Instances of this class represent a parsed X86 machine
103/// instruction.
Chris Lattner45220a82010-01-14 21:20:55 +0000104struct X86Operand : public MCParsedAsmOperand {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000105 enum KindTy {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000106 Token,
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000107 Register,
108 Immediate,
109 Memory
110 } Kind;
111
Chris Lattner29ef9a22010-01-15 18:51:29 +0000112 SMLoc StartLoc, EndLoc;
113
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000114 union {
115 struct {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000116 const char *Data;
117 unsigned Length;
118 } Tok;
119
120 struct {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000121 unsigned RegNo;
122 } Reg;
123
124 struct {
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000125 const MCExpr *Val;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000126 } Imm;
127
128 struct {
129 unsigned SegReg;
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000130 const MCExpr *Disp;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000131 unsigned BaseReg;
132 unsigned IndexReg;
133 unsigned Scale;
134 } Mem;
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000135 };
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000136
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000137 X86Operand(KindTy K, SMLoc Start, SMLoc End)
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000138 : Kind(K), StartLoc(Start), EndLoc(End) {}
Daniel Dunbarc918d602010-05-04 16:12:42 +0000139
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000140 /// getStartLoc - Get the location of the first token of this operand.
141 SMLoc getStartLoc() const { return StartLoc; }
142 /// getEndLoc - Get the location of the last token of this operand.
143 SMLoc getEndLoc() const { return EndLoc; }
144
Daniel Dunbar20927f22009-08-07 08:26:05 +0000145 StringRef getToken() const {
146 assert(Kind == Token && "Invalid access!");
147 return StringRef(Tok.Data, Tok.Length);
148 }
Daniel Dunbarc918d602010-05-04 16:12:42 +0000149 void setTokenValue(StringRef Value) {
150 assert(Kind == Token && "Invalid access!");
151 Tok.Data = Value.data();
152 Tok.Length = Value.size();
153 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000154
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000155 unsigned getReg() const {
156 assert(Kind == Register && "Invalid access!");
157 return Reg.RegNo;
158 }
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000159
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000160 const MCExpr *getImm() const {
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000161 assert(Kind == Immediate && "Invalid access!");
162 return Imm.Val;
163 }
164
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000165 const MCExpr *getMemDisp() const {
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000166 assert(Kind == Memory && "Invalid access!");
167 return Mem.Disp;
168 }
169 unsigned getMemSegReg() const {
170 assert(Kind == Memory && "Invalid access!");
171 return Mem.SegReg;
172 }
173 unsigned getMemBaseReg() const {
174 assert(Kind == Memory && "Invalid access!");
175 return Mem.BaseReg;
176 }
177 unsigned getMemIndexReg() const {
178 assert(Kind == Memory && "Invalid access!");
179 return Mem.IndexReg;
180 }
181 unsigned getMemScale() const {
182 assert(Kind == Memory && "Invalid access!");
183 return Mem.Scale;
184 }
185
Daniel Dunbara3741fa2009-08-08 07:50:56 +0000186 bool isToken() const {return Kind == Token; }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000187
188 bool isImm() const { return Kind == Immediate; }
189
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000190 bool isImmSExti16i8() const {
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000191 if (!isImm())
192 return false;
193
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000194 // If this isn't a constant expr, just assume it fits and let relaxation
195 // handle it.
196 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
197 if (!CE)
198 return true;
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000199
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000200 // Otherwise, check the value is in a range that makes sense for this
201 // extension.
202 uint64_t Value = CE->getValue();
203 return (( Value <= 0x000000000000007FULL)||
204 (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)||
205 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000206 }
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000207 bool isImmSExti32i8() const {
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000208 if (!isImm())
209 return false;
210
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000211 // If this isn't a constant expr, just assume it fits and let relaxation
212 // handle it.
213 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
214 if (!CE)
215 return true;
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000216
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000217 // Otherwise, check the value is in a range that makes sense for this
218 // extension.
219 uint64_t Value = CE->getValue();
220 return (( Value <= 0x000000000000007FULL)||
221 (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
222 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
223 }
224 bool isImmSExti64i8() const {
225 if (!isImm())
226 return false;
227
228 // If this isn't a constant expr, just assume it fits and let relaxation
229 // handle it.
230 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
231 if (!CE)
232 return true;
233
234 // Otherwise, check the value is in a range that makes sense for this
235 // extension.
236 uint64_t Value = CE->getValue();
237 return (( Value <= 0x000000000000007FULL)||
238 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
239 }
240 bool isImmSExti64i32() const {
241 if (!isImm())
242 return false;
243
244 // If this isn't a constant expr, just assume it fits and let relaxation
245 // handle it.
246 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
247 if (!CE)
248 return true;
249
250 // Otherwise, check the value is in a range that makes sense for this
251 // extension.
252 uint64_t Value = CE->getValue();
253 return (( Value <= 0x000000007FFFFFFFULL)||
254 (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000255 }
256
Daniel Dunbar20927f22009-08-07 08:26:05 +0000257 bool isMem() const { return Kind == Memory; }
258
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000259 bool isAbsMem() const {
260 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000261 !getMemIndexReg() && getMemScale() == 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000262 }
263
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000264 bool isNoSegMem() const {
265 return Kind == Memory && !getMemSegReg();
266 }
267
Daniel Dunbar20927f22009-08-07 08:26:05 +0000268 bool isReg() const { return Kind == Register; }
269
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000270 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
271 // Add as immediates when possible.
272 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
273 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
274 else
275 Inst.addOperand(MCOperand::CreateExpr(Expr));
276 }
277
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000278 void addRegOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000279 assert(N == 1 && "Invalid number of operands!");
280 Inst.addOperand(MCOperand::CreateReg(getReg()));
281 }
282
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000283 void addImmOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000284 assert(N == 1 && "Invalid number of operands!");
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000285 addExpr(Inst, getImm());
Daniel Dunbar20927f22009-08-07 08:26:05 +0000286 }
287
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000288 void addMemOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000289 assert((N == 5) && "Invalid number of operands!");
Daniel Dunbar20927f22009-08-07 08:26:05 +0000290 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
291 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
292 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000293 addExpr(Inst, getMemDisp());
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000294 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
295 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000296
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000297 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
298 assert((N == 1) && "Invalid number of operands!");
299 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
300 }
301
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000302 void addNoSegMemOperands(MCInst &Inst, unsigned N) const {
303 assert((N == 4) && "Invalid number of operands!");
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000304 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
305 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
306 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000307 addExpr(Inst, getMemDisp());
Daniel Dunbar20927f22009-08-07 08:26:05 +0000308 }
309
Chris Lattnerb4307b32010-01-15 19:28:38 +0000310 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
311 X86Operand *Res = new X86Operand(Token, Loc, Loc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000312 Res->Tok.Data = Str.data();
313 Res->Tok.Length = Str.size();
Daniel Dunbar20927f22009-08-07 08:26:05 +0000314 return Res;
315 }
316
Chris Lattner29ef9a22010-01-15 18:51:29 +0000317 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000318 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000319 Res->Reg.RegNo = RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000320 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000321 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000322
Chris Lattnerb4307b32010-01-15 19:28:38 +0000323 static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
324 X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000325 Res->Imm.Val = Val;
326 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000327 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000328
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000329 /// Create an absolute memory operand.
330 static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
331 SMLoc EndLoc) {
332 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
333 Res->Mem.SegReg = 0;
334 Res->Mem.Disp = Disp;
335 Res->Mem.BaseReg = 0;
336 Res->Mem.IndexReg = 0;
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000337 Res->Mem.Scale = 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000338 return Res;
339 }
340
341 /// Create a generalized memory operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000342 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
343 unsigned BaseReg, unsigned IndexReg,
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000344 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000345 // We should never just have a displacement, that should be parsed as an
346 // absolute memory operand.
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000347 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
348
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000349 // The scale should always be one of {1,2,4,8}.
350 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000351 "Invalid scale!");
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000352 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000353 Res->Mem.SegReg = SegReg;
354 Res->Mem.Disp = Disp;
355 Res->Mem.BaseReg = BaseReg;
356 Res->Mem.IndexReg = IndexReg;
357 Res->Mem.Scale = Scale;
358 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000359 }
360};
Daniel Dunbara3af3702009-07-20 18:55:04 +0000361
Chris Lattner37dfdec2009-07-29 06:33:53 +0000362} // end anonymous namespace.
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000363
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000364
Chris Lattner29ef9a22010-01-15 18:51:29 +0000365bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
366 SMLoc &StartLoc, SMLoc &EndLoc) {
Chris Lattner23075742010-01-15 18:27:19 +0000367 RegNo = 0;
Sean Callanan18b83232010-01-19 21:44:56 +0000368 const AsmToken &TokPercent = Parser.getTok();
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000369 assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
Chris Lattner29ef9a22010-01-15 18:51:29 +0000370 StartLoc = TokPercent.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000371 Parser.Lex(); // Eat percent token.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000372
Sean Callanan18b83232010-01-19 21:44:56 +0000373 const AsmToken &Tok = Parser.getTok();
Kevin Enderby0d6cd002009-09-16 17:18:29 +0000374 if (Tok.isNot(AsmToken::Identifier))
375 return Error(Tok.getLoc(), "invalid register name");
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000376
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000377 // FIXME: Validate register for the current architecture; we have to do
378 // validation later, so maybe there is no need for this here.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000379 RegNo = MatchRegisterName(Tok.getString());
Chris Lattnerb8d6e982010-02-09 00:34:28 +0000380
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000381 // Parse %st(1) and "%st" as "%st(0)"
382 if (RegNo == 0 && Tok.getString() == "st") {
383 RegNo = X86::ST0;
384 EndLoc = Tok.getLoc();
385 Parser.Lex(); // Eat 'st'
386
387 // Check to see if we have '(4)' after %st.
388 if (getLexer().isNot(AsmToken::LParen))
389 return false;
390 // Lex the paren.
391 getParser().Lex();
392
393 const AsmToken &IntTok = Parser.getTok();
394 if (IntTok.isNot(AsmToken::Integer))
395 return Error(IntTok.getLoc(), "expected stack index");
396 switch (IntTok.getIntVal()) {
397 case 0: RegNo = X86::ST0; break;
398 case 1: RegNo = X86::ST1; break;
399 case 2: RegNo = X86::ST2; break;
400 case 3: RegNo = X86::ST3; break;
401 case 4: RegNo = X86::ST4; break;
402 case 5: RegNo = X86::ST5; break;
403 case 6: RegNo = X86::ST6; break;
404 case 7: RegNo = X86::ST7; break;
405 default: return Error(IntTok.getLoc(), "invalid stack index");
406 }
407
408 if (getParser().Lex().isNot(AsmToken::RParen))
409 return Error(Parser.getTok().getLoc(), "expected ')'");
410
411 EndLoc = Tok.getLoc();
412 Parser.Lex(); // Eat ')'
413 return false;
414 }
415
Chris Lattner645b2092010-06-24 07:29:18 +0000416 // If this is "db[0-7]", match it as an alias
417 // for dr[0-7].
418 if (RegNo == 0 && Tok.getString().size() == 3 &&
419 Tok.getString().startswith("db")) {
420 switch (Tok.getString()[2]) {
421 case '0': RegNo = X86::DR0; break;
422 case '1': RegNo = X86::DR1; break;
423 case '2': RegNo = X86::DR2; break;
424 case '3': RegNo = X86::DR3; break;
425 case '4': RegNo = X86::DR4; break;
426 case '5': RegNo = X86::DR5; break;
427 case '6': RegNo = X86::DR6; break;
428 case '7': RegNo = X86::DR7; break;
429 }
430
431 if (RegNo != 0) {
432 EndLoc = Tok.getLoc();
433 Parser.Lex(); // Eat it.
434 return false;
435 }
436 }
437
Daniel Dunbar245f0582009-08-08 21:22:41 +0000438 if (RegNo == 0)
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000439 return Error(Tok.getLoc(), "invalid register name");
440
Chris Lattner29ef9a22010-01-15 18:51:29 +0000441 EndLoc = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000442 Parser.Lex(); // Eat identifier token.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000443 return false;
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000444}
445
Chris Lattner309264d2010-01-15 18:44:13 +0000446X86Operand *X86ATTAsmParser::ParseOperand() {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000447 switch (getLexer().getKind()) {
448 default:
Chris Lattnereef6d782010-04-17 18:56:34 +0000449 // Parse a memory operand with no segment register.
450 return ParseMemOperand(0, Parser.getTok().getLoc());
Chris Lattner23075742010-01-15 18:27:19 +0000451 case AsmToken::Percent: {
Chris Lattnereef6d782010-04-17 18:56:34 +0000452 // Read the register.
Chris Lattner23075742010-01-15 18:27:19 +0000453 unsigned RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000454 SMLoc Start, End;
455 if (ParseRegister(RegNo, Start, End)) return 0;
Chris Lattnereef6d782010-04-17 18:56:34 +0000456
457 // If this is a segment register followed by a ':', then this is the start
458 // of a memory reference, otherwise this is a normal register reference.
459 if (getLexer().isNot(AsmToken::Colon))
460 return X86Operand::CreateReg(RegNo, Start, End);
461
462
463 getParser().Lex(); // Eat the colon.
464 return ParseMemOperand(RegNo, Start);
Chris Lattner23075742010-01-15 18:27:19 +0000465 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000466 case AsmToken::Dollar: {
467 // $42 -> immediate.
Sean Callanan18b83232010-01-19 21:44:56 +0000468 SMLoc Start = Parser.getTok().getLoc(), End;
Sean Callananb9a25b72010-01-19 20:27:46 +0000469 Parser.Lex();
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000470 const MCExpr *Val;
Chris Lattner54482b42010-01-15 19:39:23 +0000471 if (getParser().ParseExpression(Val, End))
Chris Lattner309264d2010-01-15 18:44:13 +0000472 return 0;
Chris Lattnerb4307b32010-01-15 19:28:38 +0000473 return X86Operand::CreateImm(Val, Start, End);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000474 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000475 }
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000476}
477
Chris Lattnereef6d782010-04-17 18:56:34 +0000478/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
479/// has already been parsed if present.
480X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
481
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000482 // We have to disambiguate a parenthesized expression "(4+5)" from the start
483 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
Chris Lattner75f265f2010-01-24 01:07:33 +0000484 // only way to do this without lookahead is to eat the '(' and see what is
485 // after it.
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000486 const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000487 if (getLexer().isNot(AsmToken::LParen)) {
Chris Lattner54482b42010-01-15 19:39:23 +0000488 SMLoc ExprEnd;
489 if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000490
491 // After parsing the base expression we could either have a parenthesized
492 // memory address or not. If not, return now. If so, eat the (.
493 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000494 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000495 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000496 return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000497 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000498 }
499
500 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000501 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000502 } else {
503 // Okay, we have a '('. We don't know if this is an expression or not, but
504 // so we have to eat the ( to see beyond it.
Sean Callanan18b83232010-01-19 21:44:56 +0000505 SMLoc LParenLoc = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000506 Parser.Lex(); // Eat the '('.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000507
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000508 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000509 // Nothing to do here, fall into the code below with the '(' part of the
510 // memory operand consumed.
511 } else {
Chris Lattnerb4307b32010-01-15 19:28:38 +0000512 SMLoc ExprEnd;
513
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000514 // It must be an parenthesized expression, parse it now.
Chris Lattnerb4307b32010-01-15 19:28:38 +0000515 if (getParser().ParseParenExpression(Disp, ExprEnd))
Chris Lattner309264d2010-01-15 18:44:13 +0000516 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000517
518 // After parsing the base expression we could either have a parenthesized
519 // memory address or not. If not, return now. If so, eat the (.
520 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000521 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000522 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000523 return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000524 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000525 }
526
527 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000528 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000529 }
530 }
531
532 // If we reached here, then we just ate the ( of the memory operand. Process
533 // the rest of the memory operand.
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000534 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000535
Chris Lattner29ef9a22010-01-15 18:51:29 +0000536 if (getLexer().is(AsmToken::Percent)) {
537 SMLoc L;
538 if (ParseRegister(BaseReg, L, L)) return 0;
539 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000540
541 if (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000542 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000543
544 // Following the comma we should have either an index register, or a scale
545 // value. We don't support the later form, but we want to parse it
546 // correctly.
547 //
548 // Not that even though it would be completely consistent to support syntax
549 // like "1(%eax,,1)", the assembler doesn't.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000550 if (getLexer().is(AsmToken::Percent)) {
Chris Lattner29ef9a22010-01-15 18:51:29 +0000551 SMLoc L;
552 if (ParseRegister(IndexReg, L, L)) return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000553
554 if (getLexer().isNot(AsmToken::RParen)) {
555 // Parse the scale amount:
556 // ::= ',' [scale-expression]
Chris Lattner309264d2010-01-15 18:44:13 +0000557 if (getLexer().isNot(AsmToken::Comma)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000558 Error(Parser.getTok().getLoc(),
Chris Lattner309264d2010-01-15 18:44:13 +0000559 "expected comma in scale expression");
560 return 0;
561 }
Sean Callananb9a25b72010-01-19 20:27:46 +0000562 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000563
564 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000565 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000566
567 int64_t ScaleVal;
568 if (getParser().ParseAbsoluteExpression(ScaleVal))
Chris Lattner309264d2010-01-15 18:44:13 +0000569 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000570
571 // Validate the scale amount.
Chris Lattner309264d2010-01-15 18:44:13 +0000572 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
573 Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
574 return 0;
575 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000576 Scale = (unsigned)ScaleVal;
577 }
578 }
579 } else if (getLexer().isNot(AsmToken::RParen)) {
580 // Otherwise we have the unsupported form of a scale amount without an
581 // index.
Sean Callanan18b83232010-01-19 21:44:56 +0000582 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000583
584 int64_t Value;
585 if (getParser().ParseAbsoluteExpression(Value))
Chris Lattner309264d2010-01-15 18:44:13 +0000586 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000587
Chris Lattner309264d2010-01-15 18:44:13 +0000588 Error(Loc, "cannot have scale factor without index register");
589 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000590 }
591 }
592
593 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
Chris Lattner309264d2010-01-15 18:44:13 +0000594 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000595 Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
Chris Lattner309264d2010-01-15 18:44:13 +0000596 return 0;
597 }
Sean Callanan18b83232010-01-19 21:44:56 +0000598 SMLoc MemEnd = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000599 Parser.Lex(); // Eat the ')'.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000600
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000601 return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
602 MemStart, MemEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000603}
604
Chris Lattner98986712010-01-14 22:21:20 +0000605bool X86ATTAsmParser::
Benjamin Kramer38e59892010-07-14 22:38:02 +0000606ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000607 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000608 // The various flavors of pushf and popf use Requires<In32BitMode> and
609 // Requires<In64BitMode>, but the assembler doesn't yet implement that.
610 // For now, just do a manual check to prevent silent misencoding.
611 if (Is64Bit) {
612 if (Name == "popfl")
613 return Error(NameLoc, "popfl cannot be encoded in 64-bit mode");
614 else if (Name == "pushfl")
615 return Error(NameLoc, "pushfl cannot be encoded in 64-bit mode");
Kevin Enderby52a18ae2010-07-13 20:05:41 +0000616 else if (Name == "pusha")
617 return Error(NameLoc, "pusha cannot be encoded in 64-bit mode");
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000618 } else {
619 if (Name == "popfq")
620 return Error(NameLoc, "popfq cannot be encoded in 32-bit mode");
621 else if (Name == "pushfq")
622 return Error(NameLoc, "pushfq cannot be encoded in 32-bit mode");
623 }
624
Kevin Enderby09712b52010-06-08 23:48:44 +0000625 // The "Jump if rCX Zero" form jcxz is not allowed in 64-bit mode and
626 // the form jrcxz is not allowed in 32-bit mode.
627 if (Is64Bit) {
628 if (Name == "jcxz")
629 return Error(NameLoc, "jcxz cannot be encoded in 64-bit mode");
630 } else {
631 if (Name == "jrcxz")
632 return Error(NameLoc, "jrcxz cannot be encoded in 32-bit mode");
633 }
634
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000635 // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
636 // represent alternative syntaxes in the .td file, without requiring
637 // instruction duplication.
638 StringRef PatchedName = StringSwitch<StringRef>(Name)
639 .Case("sal", "shl")
640 .Case("salb", "shlb")
641 .Case("sall", "shll")
642 .Case("salq", "shlq")
643 .Case("salw", "shlw")
644 .Case("repe", "rep")
645 .Case("repz", "rep")
646 .Case("repnz", "repne")
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000647 .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
648 .Case("popf", Is64Bit ? "popfq" : "popfl")
Kevin Enderby9d31d792010-05-21 23:01:38 +0000649 .Case("retl", Is64Bit ? "retl" : "ret")
650 .Case("retq", Is64Bit ? "ret" : "retq")
Daniel Dunbar4c361972010-05-22 06:37:33 +0000651 .Case("setz", "sete")
652 .Case("setnz", "setne")
653 .Case("jz", "je")
654 .Case("jnz", "jne")
Kevin Enderbybd658912010-05-27 21:33:19 +0000655 .Case("jc", "jb")
Kevin Enderby09712b52010-06-08 23:48:44 +0000656 // FIXME: in 32-bit mode jcxz requires an AdSize prefix. In 64-bit mode
657 // jecxz requires an AdSize prefix but jecxz does not have a prefix in
658 // 32-bit mode.
Kevin Enderbybd658912010-05-27 21:33:19 +0000659 .Case("jecxz", "jcxz")
Kevin Enderby09712b52010-06-08 23:48:44 +0000660 .Case("jrcxz", "jcxz")
Kevin Enderbybd658912010-05-27 21:33:19 +0000661 .Case("jna", "jbe")
662 .Case("jnae", "jb")
663 .Case("jnb", "jae")
664 .Case("jnbe", "ja")
665 .Case("jnc", "jae")
666 .Case("jng", "jle")
667 .Case("jnge", "jl")
668 .Case("jnl", "jge")
669 .Case("jnle", "jg")
670 .Case("jpe", "jp")
671 .Case("jpo", "jnp")
Kevin Enderbyca956dc2010-05-24 20:32:23 +0000672 .Case("cmovcl", "cmovbl")
673 .Case("cmovcl", "cmovbl")
674 .Case("cmovnal", "cmovbel")
675 .Case("cmovnbl", "cmovael")
676 .Case("cmovnbel", "cmoval")
677 .Case("cmovncl", "cmovael")
678 .Case("cmovngl", "cmovlel")
679 .Case("cmovnl", "cmovgel")
680 .Case("cmovngl", "cmovlel")
681 .Case("cmovngel", "cmovll")
682 .Case("cmovnll", "cmovgel")
683 .Case("cmovnlel", "cmovgl")
684 .Case("cmovnzl", "cmovnel")
685 .Case("cmovzl", "cmovel")
Kevin Enderby5e394422010-05-28 20:59:10 +0000686 .Case("fwait", "wait")
Kevin Enderby31cc9652010-05-28 21:20:21 +0000687 .Case("movzx", "movzb")
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000688 .Default(Name);
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000689
690 // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
691 const MCExpr *ExtraImmOp = 0;
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000692 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000693 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
694 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000695 bool IsVCMP = PatchedName.startswith("vcmp");
696 unsigned SSECCIdx = IsVCMP ? 4 : 3;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000697 unsigned SSEComparisonCode = StringSwitch<unsigned>(
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000698 PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
Bruno Cardoso Lopescc69e132010-07-07 22:24:03 +0000699 .Case("eq", 0)
700 .Case("lt", 1)
701 .Case("le", 2)
702 .Case("unord", 3)
703 .Case("neq", 4)
704 .Case("nlt", 5)
705 .Case("nle", 6)
706 .Case("ord", 7)
707 .Case("eq_uq", 8)
708 .Case("nge", 9)
709 .Case("ngt", 0x0A)
710 .Case("false", 0x0B)
711 .Case("neq_oq", 0x0C)
712 .Case("ge", 0x0D)
713 .Case("gt", 0x0E)
714 .Case("true", 0x0F)
715 .Case("eq_os", 0x10)
716 .Case("lt_oq", 0x11)
717 .Case("le_oq", 0x12)
718 .Case("unord_s", 0x13)
719 .Case("neq_us", 0x14)
720 .Case("nlt_uq", 0x15)
721 .Case("nle_uq", 0x16)
722 .Case("ord_s", 0x17)
723 .Case("eq_us", 0x18)
724 .Case("nge_uq", 0x19)
725 .Case("ngt_uq", 0x1A)
726 .Case("false_os", 0x1B)
727 .Case("neq_os", 0x1C)
728 .Case("ge_oq", 0x1D)
729 .Case("gt_oq", 0x1E)
730 .Case("true_us", 0x1F)
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000731 .Default(~0U);
732 if (SSEComparisonCode != ~0U) {
733 ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode,
734 getParser().getContext());
735 if (PatchedName.endswith("ss")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000736 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000737 } else if (PatchedName.endswith("sd")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000738 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000739 } else if (PatchedName.endswith("ps")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000740 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000741 } else {
742 assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000743 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000744 }
745 }
746 }
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000747 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000748
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000749 if (ExtraImmOp)
750 Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
751
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000752 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000753
754 // Parse '*' modifier.
755 if (getLexer().is(AsmToken::Star)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000756 SMLoc Loc = Parser.getTok().getLoc();
Chris Lattnerb4307b32010-01-15 19:28:38 +0000757 Operands.push_back(X86Operand::CreateToken("*", Loc));
Sean Callananb9a25b72010-01-19 20:27:46 +0000758 Parser.Lex(); // Eat the star.
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000759 }
760
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000761 // Read the first operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000762 if (X86Operand *Op = ParseOperand())
763 Operands.push_back(Op);
764 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000765 return true;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000766
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000767 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000768 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000769
770 // Parse and remember the operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000771 if (X86Operand *Op = ParseOperand())
772 Operands.push_back(Op);
773 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000774 return true;
775 }
776 }
777
Daniel Dunbard5e77052010-03-13 00:47:29 +0000778 // FIXME: Hack to handle recognizing s{hr,ar,hl}? $1.
779 if ((Name.startswith("shr") || Name.startswith("sar") ||
780 Name.startswith("shl")) &&
781 Operands.size() == 3 &&
782 static_cast<X86Operand*>(Operands[1])->isImm() &&
783 isa<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm()) &&
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000784 cast<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm())->getValue() == 1) {
785 delete Operands[1];
Daniel Dunbard5e77052010-03-13 00:47:29 +0000786 Operands.erase(Operands.begin() + 1);
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000787 }
Daniel Dunbard5e77052010-03-13 00:47:29 +0000788
Kevin Enderbycf50a532010-05-25 20:52:34 +0000789 // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
790 // "f{mul*,add*,sub*,div*} $op"
791 if ((Name.startswith("fmul") || Name.startswith("fadd") ||
792 Name.startswith("fsub") || Name.startswith("fdiv")) &&
793 Operands.size() == 3 &&
794 static_cast<X86Operand*>(Operands[2])->isReg() &&
795 static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
796 delete Operands[2];
797 Operands.erase(Operands.begin() + 2);
798 }
799
Chris Lattner98986712010-01-14 22:21:20 +0000800 return false;
Daniel Dunbara3af3702009-07-20 18:55:04 +0000801}
802
Kevin Enderby9c656452009-09-10 20:51:44 +0000803bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
804 StringRef IDVal = DirectiveID.getIdentifier();
805 if (IDVal == ".word")
806 return ParseDirectiveWord(2, DirectiveID.getLoc());
807 return true;
808}
809
810/// ParseDirectiveWord
811/// ::= .word [ expression (, expression)* ]
812bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
813 if (getLexer().isNot(AsmToken::EndOfStatement)) {
814 for (;;) {
815 const MCExpr *Value;
816 if (getParser().ParseExpression(Value))
817 return true;
818
Chris Lattneraaec2052010-01-19 19:46:13 +0000819 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
Kevin Enderby9c656452009-09-10 20:51:44 +0000820
821 if (getLexer().is(AsmToken::EndOfStatement))
822 break;
823
824 // FIXME: Improve diagnostic.
825 if (getLexer().isNot(AsmToken::Comma))
826 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000827 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000828 }
829 }
830
Sean Callananb9a25b72010-01-19 20:27:46 +0000831 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000832 return false;
833}
834
Chris Lattnerb5505d02010-05-13 00:02:47 +0000835/// LowerMOffset - Lower an 'moffset' form of an instruction, which just has a
836/// imm operand, to having "rm" or "mr" operands with the offset in the disp
837/// field.
838static void LowerMOffset(MCInst &Inst, unsigned Opc, unsigned RegNo,
839 bool isMR) {
840 MCOperand Disp = Inst.getOperand(0);
841
842 // Start over with an empty instruction.
843 Inst = MCInst();
844 Inst.setOpcode(Opc);
845
846 if (!isMR)
847 Inst.addOperand(MCOperand::CreateReg(RegNo));
848
849 // Add the mem operand.
850 Inst.addOperand(MCOperand::CreateReg(0)); // Segment
851 Inst.addOperand(MCOperand::CreateImm(1)); // Scale
852 Inst.addOperand(MCOperand::CreateReg(0)); // IndexReg
853 Inst.addOperand(Disp); // Displacement
854 Inst.addOperand(MCOperand::CreateReg(0)); // BaseReg
855
856 if (isMR)
857 Inst.addOperand(MCOperand::CreateReg(RegNo));
858}
859
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000860// FIXME: Custom X86 cleanup function to implement a temporary hack to handle
861// matching INCL/DECL correctly for x86_64. This needs to be replaced by a
862// proper mechanism for supporting (ambiguous) feature dependent instructions.
863void X86ATTAsmParser::InstructionCleanup(MCInst &Inst) {
864 if (!Is64Bit) return;
865
866 switch (Inst.getOpcode()) {
867 case X86::DEC16r: Inst.setOpcode(X86::DEC64_16r); break;
868 case X86::DEC16m: Inst.setOpcode(X86::DEC64_16m); break;
869 case X86::DEC32r: Inst.setOpcode(X86::DEC64_32r); break;
870 case X86::DEC32m: Inst.setOpcode(X86::DEC64_32m); break;
871 case X86::INC16r: Inst.setOpcode(X86::INC64_16r); break;
872 case X86::INC16m: Inst.setOpcode(X86::INC64_16m); break;
873 case X86::INC32r: Inst.setOpcode(X86::INC64_32r); break;
874 case X86::INC32m: Inst.setOpcode(X86::INC64_32m); break;
Chris Lattnerb5505d02010-05-13 00:02:47 +0000875
876 // moffset instructions are x86-32 only.
877 case X86::MOV8o8a: LowerMOffset(Inst, X86::MOV8rm , X86::AL , false); break;
878 case X86::MOV16o16a: LowerMOffset(Inst, X86::MOV16rm, X86::AX , false); break;
879 case X86::MOV32o32a: LowerMOffset(Inst, X86::MOV32rm, X86::EAX, false); break;
880 case X86::MOV8ao8: LowerMOffset(Inst, X86::MOV8mr , X86::AL , true); break;
881 case X86::MOV16ao16: LowerMOffset(Inst, X86::MOV16mr, X86::AX , true); break;
882 case X86::MOV32ao32: LowerMOffset(Inst, X86::MOV32mr, X86::EAX, true); break;
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000883 }
884}
885
Daniel Dunbarc918d602010-05-04 16:12:42 +0000886bool
887X86ATTAsmParser::MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*>
888 &Operands,
889 MCInst &Inst) {
890 // First, try a direct match.
891 if (!MatchInstructionImpl(Operands, Inst))
892 return false;
893
894 // Ignore anything which is obviously not a suffix match.
895 if (Operands.size() == 0)
896 return true;
897 X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
898 if (!Op->isToken() || Op->getToken().size() > 15)
899 return true;
900
901 // FIXME: Ideally, we would only attempt suffix matches for things which are
902 // valid prefixes, and we could just infer the right unambiguous
903 // type. However, that requires substantially more matcher support than the
904 // following hack.
905
906 // Change the operand to point to a temporary token.
907 char Tmp[16];
908 StringRef Base = Op->getToken();
909 memcpy(Tmp, Base.data(), Base.size());
910 Op->setTokenValue(StringRef(Tmp, Base.size() + 1));
911
912 // Check for the various suffix matches.
913 Tmp[Base.size()] = 'b';
914 bool MatchB = MatchInstructionImpl(Operands, Inst);
915 Tmp[Base.size()] = 'w';
916 bool MatchW = MatchInstructionImpl(Operands, Inst);
917 Tmp[Base.size()] = 'l';
918 bool MatchL = MatchInstructionImpl(Operands, Inst);
Daniel Dunbar04814492010-05-12 00:54:20 +0000919 Tmp[Base.size()] = 'q';
920 bool MatchQ = MatchInstructionImpl(Operands, Inst);
Daniel Dunbarc918d602010-05-04 16:12:42 +0000921
922 // Restore the old token.
923 Op->setTokenValue(Base);
924
925 // If exactly one matched, then we treat that as a successful match (and the
926 // instruction will already have been filled in correctly, since the failing
927 // matches won't have modified it).
Daniel Dunbar04814492010-05-12 00:54:20 +0000928 if (MatchB + MatchW + MatchL + MatchQ == 3)
Daniel Dunbarc918d602010-05-04 16:12:42 +0000929 return false;
930
Daniel Dunbarc918d602010-05-04 16:12:42 +0000931 // Otherwise, the match failed.
932 return true;
933}
934
935
Sean Callanane88f5522010-01-23 02:43:15 +0000936extern "C" void LLVMInitializeX86AsmLexer();
937
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000938// Force static initialization.
939extern "C" void LLVMInitializeX86AsmParser() {
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000940 RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
941 RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
Sean Callanane88f5522010-01-23 02:43:15 +0000942 LLVMInitializeX86AsmLexer();
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000943}
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000944
945#include "X86GenAsmMatcher.inc"