blob: c33678cb262c1ee25cbf1b28e2255c00a0a22d0e [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 Dunbar54074b52010-07-19 05:44:09 +000012#include "X86Subtarget.h"
Daniel Dunbardbd692a2009-07-20 20:01:54 +000013#include "llvm/ADT/SmallVector.h"
Daniel Dunbar1b6c0602010-02-10 21:19:28 +000014#include "llvm/ADT/StringSwitch.h"
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000015#include "llvm/ADT/Twine.h"
Kevin Enderby9c656452009-09-10 20:51:44 +000016#include "llvm/MC/MCStreamer.h"
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +000017#include "llvm/MC/MCExpr.h"
Daniel Dunbara027d222009-07-31 02:32:59 +000018#include "llvm/MC/MCInst.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
20#include "llvm/MC/MCParser/MCAsmParser.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000022#include "llvm/Support/SourceMgr.h"
Daniel Dunbar092a9dd2009-07-17 20:42:00 +000023#include "llvm/Target/TargetRegistry.h"
24#include "llvm/Target/TargetAsmParser.h"
25using namespace llvm;
26
27namespace {
Benjamin Kramerc6b79ac2009-07-31 11:35:26 +000028struct X86Operand;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000029
30class X86ATTAsmParser : public TargetAsmParser {
31 MCAsmParser &Parser;
Daniel Dunbard73ada72010-07-19 00:33:49 +000032 TargetMachine &TM;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000033
Daniel Dunbarf98bc632010-03-18 20:06:02 +000034protected:
35 unsigned Is64Bit : 1;
36
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000037private:
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000038 MCAsmParser &getParser() const { return Parser; }
39
40 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
41
42 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
43
44 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
45
Chris Lattner29ef9a22010-01-15 18:51:29 +000046 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000047
Chris Lattner309264d2010-01-15 18:44:13 +000048 X86Operand *ParseOperand();
Chris Lattnereef6d782010-04-17 18:56:34 +000049 X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
Kevin Enderby9c656452009-09-10 20:51:44 +000050
51 bool ParseDirectiveWord(unsigned Size, SMLoc L);
52
Daniel Dunbarf98bc632010-03-18 20:06:02 +000053 void InstructionCleanup(MCInst &Inst);
54
Chris Lattner98986712010-01-14 22:21:20 +000055 bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbar20927f22009-08-07 08:26:05 +000056 MCInst &Inst);
57
Daniel Dunbar54074b52010-07-19 05:44:09 +000058 /// @name Auto-generated Matcher Functions
59 /// {
60
61 unsigned ComputeAvailableFeatures(const X86Subtarget *Subtarget) const;
62
Daniel Dunbarc918d602010-05-04 16:12:42 +000063 bool MatchInstructionImpl(
64 const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst);
65
Daniel Dunbar0e2771f2009-07-29 00:02:19 +000066 /// }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000067
68public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000069 X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
Daniel Dunbar54074b52010-07-19 05:44:09 +000070 : TargetAsmParser(T), Parser(_Parser), TM(TM) {
71
72 // Initialize the set of available features.
73 setAvailableFeatures(ComputeAvailableFeatures(
74 &TM.getSubtarget<X86Subtarget>()));
75 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000076
Benjamin Kramer38e59892010-07-14 22:38:02 +000077 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +000078 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderby9c656452009-09-10 20:51:44 +000079
80 virtual bool ParseDirective(AsmToken DirectiveID);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +000081};
Daniel Dunbarf98bc632010-03-18 20:06:02 +000082
83class X86_32ATTAsmParser : public X86ATTAsmParser {
84public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000085 X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
86 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbarf98bc632010-03-18 20:06:02 +000087 Is64Bit = false;
88 }
89};
90
91class X86_64ATTAsmParser : public X86ATTAsmParser {
92public:
Daniel Dunbard73ada72010-07-19 00:33:49 +000093 X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
94 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbarf98bc632010-03-18 20:06:02 +000095 Is64Bit = true;
96 }
97};
98
Chris Lattner37dfdec2009-07-29 06:33:53 +000099} // end anonymous namespace
100
Sean Callanane9b466d2010-01-23 00:40:33 +0000101/// @name Auto-generated Match Functions
102/// {
103
Chris Lattnerb8d6e982010-02-09 00:34:28 +0000104static unsigned MatchRegisterName(StringRef Name);
Sean Callanane9b466d2010-01-23 00:40:33 +0000105
106/// }
Chris Lattner37dfdec2009-07-29 06:33:53 +0000107
108namespace {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000109
110/// X86Operand - Instances of this class represent a parsed X86 machine
111/// instruction.
Chris Lattner45220a82010-01-14 21:20:55 +0000112struct X86Operand : public MCParsedAsmOperand {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000113 enum KindTy {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000114 Token,
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000115 Register,
116 Immediate,
117 Memory
118 } Kind;
119
Chris Lattner29ef9a22010-01-15 18:51:29 +0000120 SMLoc StartLoc, EndLoc;
121
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000122 union {
123 struct {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000124 const char *Data;
125 unsigned Length;
126 } Tok;
127
128 struct {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000129 unsigned RegNo;
130 } Reg;
131
132 struct {
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000133 const MCExpr *Val;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000134 } Imm;
135
136 struct {
137 unsigned SegReg;
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000138 const MCExpr *Disp;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000139 unsigned BaseReg;
140 unsigned IndexReg;
141 unsigned Scale;
142 } Mem;
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000143 };
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000144
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000145 X86Operand(KindTy K, SMLoc Start, SMLoc End)
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000146 : Kind(K), StartLoc(Start), EndLoc(End) {}
Daniel Dunbarc918d602010-05-04 16:12:42 +0000147
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000148 /// getStartLoc - Get the location of the first token of this operand.
149 SMLoc getStartLoc() const { return StartLoc; }
150 /// getEndLoc - Get the location of the last token of this operand.
151 SMLoc getEndLoc() const { return EndLoc; }
152
Daniel Dunbar20927f22009-08-07 08:26:05 +0000153 StringRef getToken() const {
154 assert(Kind == Token && "Invalid access!");
155 return StringRef(Tok.Data, Tok.Length);
156 }
Daniel Dunbarc918d602010-05-04 16:12:42 +0000157 void setTokenValue(StringRef Value) {
158 assert(Kind == Token && "Invalid access!");
159 Tok.Data = Value.data();
160 Tok.Length = Value.size();
161 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000162
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000163 unsigned getReg() const {
164 assert(Kind == Register && "Invalid access!");
165 return Reg.RegNo;
166 }
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000167
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000168 const MCExpr *getImm() const {
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000169 assert(Kind == Immediate && "Invalid access!");
170 return Imm.Val;
171 }
172
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000173 const MCExpr *getMemDisp() const {
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000174 assert(Kind == Memory && "Invalid access!");
175 return Mem.Disp;
176 }
177 unsigned getMemSegReg() const {
178 assert(Kind == Memory && "Invalid access!");
179 return Mem.SegReg;
180 }
181 unsigned getMemBaseReg() const {
182 assert(Kind == Memory && "Invalid access!");
183 return Mem.BaseReg;
184 }
185 unsigned getMemIndexReg() const {
186 assert(Kind == Memory && "Invalid access!");
187 return Mem.IndexReg;
188 }
189 unsigned getMemScale() const {
190 assert(Kind == Memory && "Invalid access!");
191 return Mem.Scale;
192 }
193
Daniel Dunbara3741fa2009-08-08 07:50:56 +0000194 bool isToken() const {return Kind == Token; }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000195
196 bool isImm() const { return Kind == Immediate; }
197
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000198 bool isImmSExti16i8() const {
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000199 if (!isImm())
200 return false;
201
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000202 // If this isn't a constant expr, just assume it fits and let relaxation
203 // handle it.
204 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
205 if (!CE)
206 return true;
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000207
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000208 // Otherwise, check the value is in a range that makes sense for this
209 // extension.
210 uint64_t Value = CE->getValue();
211 return (( Value <= 0x000000000000007FULL)||
212 (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)||
213 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar5fe63382009-08-09 07:20:21 +0000214 }
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000215 bool isImmSExti32i8() const {
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000216 if (!isImm())
217 return false;
218
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000219 // If this isn't a constant expr, just assume it fits and let relaxation
220 // handle it.
221 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
222 if (!CE)
223 return true;
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000224
Daniel Dunbar62e4c672010-05-22 21:02:33 +0000225 // Otherwise, check the value is in a range that makes sense for this
226 // extension.
227 uint64_t Value = CE->getValue();
228 return (( Value <= 0x000000000000007FULL)||
229 (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
230 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
231 }
232 bool isImmSExti64i8() const {
233 if (!isImm())
234 return false;
235
236 // If this isn't a constant expr, just assume it fits and let relaxation
237 // handle it.
238 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
239 if (!CE)
240 return true;
241
242 // Otherwise, check the value is in a range that makes sense for this
243 // extension.
244 uint64_t Value = CE->getValue();
245 return (( Value <= 0x000000000000007FULL)||
246 (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
247 }
248 bool isImmSExti64i32() const {
249 if (!isImm())
250 return false;
251
252 // If this isn't a constant expr, just assume it fits and let relaxation
253 // handle it.
254 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
255 if (!CE)
256 return true;
257
258 // Otherwise, check the value is in a range that makes sense for this
259 // extension.
260 uint64_t Value = CE->getValue();
261 return (( Value <= 0x000000007FFFFFFFULL)||
262 (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
Daniel Dunbar1fe591d2010-05-20 20:20:39 +0000263 }
264
Daniel Dunbar20927f22009-08-07 08:26:05 +0000265 bool isMem() const { return Kind == Memory; }
266
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000267 bool isAbsMem() const {
268 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000269 !getMemIndexReg() && getMemScale() == 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000270 }
271
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000272 bool isNoSegMem() const {
273 return Kind == Memory && !getMemSegReg();
274 }
275
Daniel Dunbar20927f22009-08-07 08:26:05 +0000276 bool isReg() const { return Kind == Register; }
277
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000278 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
279 // Add as immediates when possible.
280 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
281 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
282 else
283 Inst.addOperand(MCOperand::CreateExpr(Expr));
284 }
285
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000286 void addRegOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000287 assert(N == 1 && "Invalid number of operands!");
288 Inst.addOperand(MCOperand::CreateReg(getReg()));
289 }
290
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000291 void addImmOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar20927f22009-08-07 08:26:05 +0000292 assert(N == 1 && "Invalid number of operands!");
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000293 addExpr(Inst, getImm());
Daniel Dunbar20927f22009-08-07 08:26:05 +0000294 }
295
Daniel Dunbar5c468e32009-08-10 21:00:45 +0000296 void addMemOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000297 assert((N == 5) && "Invalid number of operands!");
Daniel Dunbar20927f22009-08-07 08:26:05 +0000298 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
299 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
300 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000301 addExpr(Inst, getMemDisp());
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000302 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
303 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000304
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000305 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
306 assert((N == 1) && "Invalid number of operands!");
307 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
308 }
309
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000310 void addNoSegMemOperands(MCInst &Inst, unsigned N) const {
311 assert((N == 4) && "Invalid number of operands!");
Daniel Dunbarec2b1f12010-01-30 00:24:00 +0000312 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
313 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
314 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar9c60f532010-02-13 00:17:21 +0000315 addExpr(Inst, getMemDisp());
Daniel Dunbar20927f22009-08-07 08:26:05 +0000316 }
317
Chris Lattnerb4307b32010-01-15 19:28:38 +0000318 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
319 X86Operand *Res = new X86Operand(Token, Loc, Loc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000320 Res->Tok.Data = Str.data();
321 Res->Tok.Length = Str.size();
Daniel Dunbar20927f22009-08-07 08:26:05 +0000322 return Res;
323 }
324
Chris Lattner29ef9a22010-01-15 18:51:29 +0000325 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
Chris Lattner1f19f0f2010-01-15 19:06:59 +0000326 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000327 Res->Reg.RegNo = RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000328 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000329 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000330
Chris Lattnerb4307b32010-01-15 19:28:38 +0000331 static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
332 X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000333 Res->Imm.Val = Val;
334 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000335 }
Daniel Dunbar20927f22009-08-07 08:26:05 +0000336
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000337 /// Create an absolute memory operand.
338 static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
339 SMLoc EndLoc) {
340 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
341 Res->Mem.SegReg = 0;
342 Res->Mem.Disp = Disp;
343 Res->Mem.BaseReg = 0;
344 Res->Mem.IndexReg = 0;
Daniel Dunbar7b9147a2010-02-02 21:44:16 +0000345 Res->Mem.Scale = 1;
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000346 return Res;
347 }
348
349 /// Create a generalized memory operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000350 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
351 unsigned BaseReg, unsigned IndexReg,
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000352 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000353 // We should never just have a displacement, that should be parsed as an
354 // absolute memory operand.
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000355 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
356
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000357 // The scale should always be one of {1,2,4,8}.
358 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000359 "Invalid scale!");
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000360 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
Chris Lattner29ef9a22010-01-15 18:51:29 +0000361 Res->Mem.SegReg = SegReg;
362 Res->Mem.Disp = Disp;
363 Res->Mem.BaseReg = BaseReg;
364 Res->Mem.IndexReg = IndexReg;
365 Res->Mem.Scale = Scale;
366 return Res;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000367 }
368};
Daniel Dunbara3af3702009-07-20 18:55:04 +0000369
Chris Lattner37dfdec2009-07-29 06:33:53 +0000370} // end anonymous namespace.
Daniel Dunbara2edbab2009-07-28 20:47:52 +0000371
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000372
Chris Lattner29ef9a22010-01-15 18:51:29 +0000373bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
374 SMLoc &StartLoc, SMLoc &EndLoc) {
Chris Lattner23075742010-01-15 18:27:19 +0000375 RegNo = 0;
Sean Callanan18b83232010-01-19 21:44:56 +0000376 const AsmToken &TokPercent = Parser.getTok();
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000377 assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
Chris Lattner29ef9a22010-01-15 18:51:29 +0000378 StartLoc = TokPercent.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000379 Parser.Lex(); // Eat percent token.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000380
Sean Callanan18b83232010-01-19 21:44:56 +0000381 const AsmToken &Tok = Parser.getTok();
Kevin Enderby0d6cd002009-09-16 17:18:29 +0000382 if (Tok.isNot(AsmToken::Identifier))
383 return Error(Tok.getLoc(), "invalid register name");
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000384
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000385 // FIXME: Validate register for the current architecture; we have to do
386 // validation later, so maybe there is no need for this here.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000387 RegNo = MatchRegisterName(Tok.getString());
Chris Lattnerb8d6e982010-02-09 00:34:28 +0000388
Chris Lattnere16b0fc2010-02-09 00:49:22 +0000389 // Parse %st(1) and "%st" as "%st(0)"
390 if (RegNo == 0 && Tok.getString() == "st") {
391 RegNo = X86::ST0;
392 EndLoc = Tok.getLoc();
393 Parser.Lex(); // Eat 'st'
394
395 // Check to see if we have '(4)' after %st.
396 if (getLexer().isNot(AsmToken::LParen))
397 return false;
398 // Lex the paren.
399 getParser().Lex();
400
401 const AsmToken &IntTok = Parser.getTok();
402 if (IntTok.isNot(AsmToken::Integer))
403 return Error(IntTok.getLoc(), "expected stack index");
404 switch (IntTok.getIntVal()) {
405 case 0: RegNo = X86::ST0; break;
406 case 1: RegNo = X86::ST1; break;
407 case 2: RegNo = X86::ST2; break;
408 case 3: RegNo = X86::ST3; break;
409 case 4: RegNo = X86::ST4; break;
410 case 5: RegNo = X86::ST5; break;
411 case 6: RegNo = X86::ST6; break;
412 case 7: RegNo = X86::ST7; break;
413 default: return Error(IntTok.getLoc(), "invalid stack index");
414 }
415
416 if (getParser().Lex().isNot(AsmToken::RParen))
417 return Error(Parser.getTok().getLoc(), "expected ')'");
418
419 EndLoc = Tok.getLoc();
420 Parser.Lex(); // Eat ')'
421 return false;
422 }
423
Chris Lattner645b2092010-06-24 07:29:18 +0000424 // If this is "db[0-7]", match it as an alias
425 // for dr[0-7].
426 if (RegNo == 0 && Tok.getString().size() == 3 &&
427 Tok.getString().startswith("db")) {
428 switch (Tok.getString()[2]) {
429 case '0': RegNo = X86::DR0; break;
430 case '1': RegNo = X86::DR1; break;
431 case '2': RegNo = X86::DR2; break;
432 case '3': RegNo = X86::DR3; break;
433 case '4': RegNo = X86::DR4; break;
434 case '5': RegNo = X86::DR5; break;
435 case '6': RegNo = X86::DR6; break;
436 case '7': RegNo = X86::DR7; break;
437 }
438
439 if (RegNo != 0) {
440 EndLoc = Tok.getLoc();
441 Parser.Lex(); // Eat it.
442 return false;
443 }
444 }
445
Daniel Dunbar245f0582009-08-08 21:22:41 +0000446 if (RegNo == 0)
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000447 return Error(Tok.getLoc(), "invalid register name");
448
Chris Lattner29ef9a22010-01-15 18:51:29 +0000449 EndLoc = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000450 Parser.Lex(); // Eat identifier token.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000451 return false;
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000452}
453
Chris Lattner309264d2010-01-15 18:44:13 +0000454X86Operand *X86ATTAsmParser::ParseOperand() {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000455 switch (getLexer().getKind()) {
456 default:
Chris Lattnereef6d782010-04-17 18:56:34 +0000457 // Parse a memory operand with no segment register.
458 return ParseMemOperand(0, Parser.getTok().getLoc());
Chris Lattner23075742010-01-15 18:27:19 +0000459 case AsmToken::Percent: {
Chris Lattnereef6d782010-04-17 18:56:34 +0000460 // Read the register.
Chris Lattner23075742010-01-15 18:27:19 +0000461 unsigned RegNo;
Chris Lattner29ef9a22010-01-15 18:51:29 +0000462 SMLoc Start, End;
463 if (ParseRegister(RegNo, Start, End)) return 0;
Chris Lattnereef6d782010-04-17 18:56:34 +0000464
465 // If this is a segment register followed by a ':', then this is the start
466 // of a memory reference, otherwise this is a normal register reference.
467 if (getLexer().isNot(AsmToken::Colon))
468 return X86Operand::CreateReg(RegNo, Start, End);
469
470
471 getParser().Lex(); // Eat the colon.
472 return ParseMemOperand(RegNo, Start);
Chris Lattner23075742010-01-15 18:27:19 +0000473 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000474 case AsmToken::Dollar: {
475 // $42 -> immediate.
Sean Callanan18b83232010-01-19 21:44:56 +0000476 SMLoc Start = Parser.getTok().getLoc(), End;
Sean Callananb9a25b72010-01-19 20:27:46 +0000477 Parser.Lex();
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000478 const MCExpr *Val;
Chris Lattner54482b42010-01-15 19:39:23 +0000479 if (getParser().ParseExpression(Val, End))
Chris Lattner309264d2010-01-15 18:44:13 +0000480 return 0;
Chris Lattnerb4307b32010-01-15 19:28:38 +0000481 return X86Operand::CreateImm(Val, Start, End);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000482 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000483 }
Daniel Dunbardbd692a2009-07-20 20:01:54 +0000484}
485
Chris Lattnereef6d782010-04-17 18:56:34 +0000486/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
487/// has already been parsed if present.
488X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
489
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000490 // We have to disambiguate a parenthesized expression "(4+5)" from the start
491 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
Chris Lattner75f265f2010-01-24 01:07:33 +0000492 // only way to do this without lookahead is to eat the '(' and see what is
493 // after it.
Daniel Dunbar8c2eebe2009-08-31 08:08:38 +0000494 const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000495 if (getLexer().isNot(AsmToken::LParen)) {
Chris Lattner54482b42010-01-15 19:39:23 +0000496 SMLoc ExprEnd;
497 if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000498
499 // After parsing the base expression we could either have a parenthesized
500 // memory address or not. If not, return now. If so, eat the (.
501 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000502 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000503 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000504 return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000505 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000506 }
507
508 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000509 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000510 } else {
511 // Okay, we have a '('. We don't know if this is an expression or not, but
512 // so we have to eat the ( to see beyond it.
Sean Callanan18b83232010-01-19 21:44:56 +0000513 SMLoc LParenLoc = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000514 Parser.Lex(); // Eat the '('.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000515
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000516 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000517 // Nothing to do here, fall into the code below with the '(' part of the
518 // memory operand consumed.
519 } else {
Chris Lattnerb4307b32010-01-15 19:28:38 +0000520 SMLoc ExprEnd;
521
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000522 // It must be an parenthesized expression, parse it now.
Chris Lattnerb4307b32010-01-15 19:28:38 +0000523 if (getParser().ParseParenExpression(Disp, ExprEnd))
Chris Lattner309264d2010-01-15 18:44:13 +0000524 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000525
526 // After parsing the base expression we could either have a parenthesized
527 // memory address or not. If not, return now. If so, eat the (.
528 if (getLexer().isNot(AsmToken::LParen)) {
Daniel Dunbarc09e4112009-07-31 22:22:54 +0000529 // Unless we have a segment register, treat this as an immediate.
Chris Lattner309264d2010-01-15 18:44:13 +0000530 if (SegReg == 0)
Daniel Dunbarb834f5d2010-01-30 01:02:48 +0000531 return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000532 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000533 }
534
535 // Eat the '('.
Sean Callananb9a25b72010-01-19 20:27:46 +0000536 Parser.Lex();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000537 }
538 }
539
540 // If we reached here, then we just ate the ( of the memory operand. Process
541 // the rest of the memory operand.
Daniel Dunbar022e2a82009-07-31 20:53:16 +0000542 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000543
Chris Lattner29ef9a22010-01-15 18:51:29 +0000544 if (getLexer().is(AsmToken::Percent)) {
545 SMLoc L;
546 if (ParseRegister(BaseReg, L, L)) return 0;
547 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000548
549 if (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000550 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000551
552 // Following the comma we should have either an index register, or a scale
553 // value. We don't support the later form, but we want to parse it
554 // correctly.
555 //
556 // Not that even though it would be completely consistent to support syntax
557 // like "1(%eax,,1)", the assembler doesn't.
Kevin Enderby7b4608d2009-09-03 17:15:07 +0000558 if (getLexer().is(AsmToken::Percent)) {
Chris Lattner29ef9a22010-01-15 18:51:29 +0000559 SMLoc L;
560 if (ParseRegister(IndexReg, L, L)) return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000561
562 if (getLexer().isNot(AsmToken::RParen)) {
563 // Parse the scale amount:
564 // ::= ',' [scale-expression]
Chris Lattner309264d2010-01-15 18:44:13 +0000565 if (getLexer().isNot(AsmToken::Comma)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000566 Error(Parser.getTok().getLoc(),
Chris Lattner309264d2010-01-15 18:44:13 +0000567 "expected comma in scale expression");
568 return 0;
569 }
Sean Callananb9a25b72010-01-19 20:27:46 +0000570 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000571
572 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000573 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000574
575 int64_t ScaleVal;
576 if (getParser().ParseAbsoluteExpression(ScaleVal))
Chris Lattner309264d2010-01-15 18:44:13 +0000577 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000578
579 // Validate the scale amount.
Chris Lattner309264d2010-01-15 18:44:13 +0000580 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
581 Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
582 return 0;
583 }
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000584 Scale = (unsigned)ScaleVal;
585 }
586 }
587 } else if (getLexer().isNot(AsmToken::RParen)) {
588 // Otherwise we have the unsupported form of a scale amount without an
589 // index.
Sean Callanan18b83232010-01-19 21:44:56 +0000590 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000591
592 int64_t Value;
593 if (getParser().ParseAbsoluteExpression(Value))
Chris Lattner309264d2010-01-15 18:44:13 +0000594 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000595
Chris Lattner309264d2010-01-15 18:44:13 +0000596 Error(Loc, "cannot have scale factor without index register");
597 return 0;
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000598 }
599 }
600
601 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
Chris Lattner309264d2010-01-15 18:44:13 +0000602 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000603 Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
Chris Lattner309264d2010-01-15 18:44:13 +0000604 return 0;
605 }
Sean Callanan18b83232010-01-19 21:44:56 +0000606 SMLoc MemEnd = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +0000607 Parser.Lex(); // Eat the ')'.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000608
Chris Lattner0a3c5a52010-01-15 19:33:43 +0000609 return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
610 MemStart, MemEnd);
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000611}
612
Chris Lattner98986712010-01-14 22:21:20 +0000613bool X86ATTAsmParser::
Benjamin Kramer38e59892010-07-14 22:38:02 +0000614ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattner98986712010-01-14 22:21:20 +0000615 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000616 // The various flavors of pushf and popf use Requires<In32BitMode> and
617 // Requires<In64BitMode>, but the assembler doesn't yet implement that.
618 // For now, just do a manual check to prevent silent misencoding.
619 if (Is64Bit) {
620 if (Name == "popfl")
621 return Error(NameLoc, "popfl cannot be encoded in 64-bit mode");
622 else if (Name == "pushfl")
623 return Error(NameLoc, "pushfl cannot be encoded in 64-bit mode");
Kevin Enderby52a18ae2010-07-13 20:05:41 +0000624 else if (Name == "pusha")
625 return Error(NameLoc, "pusha cannot be encoded in 64-bit mode");
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000626 } else {
627 if (Name == "popfq")
628 return Error(NameLoc, "popfq cannot be encoded in 32-bit mode");
629 else if (Name == "pushfq")
630 return Error(NameLoc, "pushfq cannot be encoded in 32-bit mode");
631 }
632
Kevin Enderby09712b52010-06-08 23:48:44 +0000633 // The "Jump if rCX Zero" form jcxz is not allowed in 64-bit mode and
634 // the form jrcxz is not allowed in 32-bit mode.
635 if (Is64Bit) {
636 if (Name == "jcxz")
637 return Error(NameLoc, "jcxz cannot be encoded in 64-bit mode");
638 } else {
639 if (Name == "jrcxz")
640 return Error(NameLoc, "jrcxz cannot be encoded in 32-bit mode");
641 }
642
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000643 // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
644 // represent alternative syntaxes in the .td file, without requiring
645 // instruction duplication.
646 StringRef PatchedName = StringSwitch<StringRef>(Name)
647 .Case("sal", "shl")
648 .Case("salb", "shlb")
649 .Case("sall", "shll")
650 .Case("salq", "shlq")
651 .Case("salw", "shlw")
652 .Case("repe", "rep")
653 .Case("repz", "rep")
654 .Case("repnz", "repne")
Dan Gohmane5e4ff92010-05-20 16:16:00 +0000655 .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
656 .Case("popf", Is64Bit ? "popfq" : "popfl")
Kevin Enderby9d31d792010-05-21 23:01:38 +0000657 .Case("retl", Is64Bit ? "retl" : "ret")
658 .Case("retq", Is64Bit ? "ret" : "retq")
Daniel Dunbar4c361972010-05-22 06:37:33 +0000659 .Case("setz", "sete")
660 .Case("setnz", "setne")
661 .Case("jz", "je")
662 .Case("jnz", "jne")
Kevin Enderbybd658912010-05-27 21:33:19 +0000663 .Case("jc", "jb")
Kevin Enderby09712b52010-06-08 23:48:44 +0000664 // FIXME: in 32-bit mode jcxz requires an AdSize prefix. In 64-bit mode
665 // jecxz requires an AdSize prefix but jecxz does not have a prefix in
666 // 32-bit mode.
Kevin Enderbybd658912010-05-27 21:33:19 +0000667 .Case("jecxz", "jcxz")
Kevin Enderby09712b52010-06-08 23:48:44 +0000668 .Case("jrcxz", "jcxz")
Kevin Enderbybd658912010-05-27 21:33:19 +0000669 .Case("jna", "jbe")
670 .Case("jnae", "jb")
671 .Case("jnb", "jae")
672 .Case("jnbe", "ja")
673 .Case("jnc", "jae")
674 .Case("jng", "jle")
675 .Case("jnge", "jl")
676 .Case("jnl", "jge")
677 .Case("jnle", "jg")
678 .Case("jpe", "jp")
679 .Case("jpo", "jnp")
Kevin Enderbyca956dc2010-05-24 20:32:23 +0000680 .Case("cmovcl", "cmovbl")
681 .Case("cmovcl", "cmovbl")
682 .Case("cmovnal", "cmovbel")
683 .Case("cmovnbl", "cmovael")
684 .Case("cmovnbel", "cmoval")
685 .Case("cmovncl", "cmovael")
686 .Case("cmovngl", "cmovlel")
687 .Case("cmovnl", "cmovgel")
688 .Case("cmovngl", "cmovlel")
689 .Case("cmovngel", "cmovll")
690 .Case("cmovnll", "cmovgel")
691 .Case("cmovnlel", "cmovgl")
692 .Case("cmovnzl", "cmovnel")
693 .Case("cmovzl", "cmovel")
Kevin Enderby5e394422010-05-28 20:59:10 +0000694 .Case("fwait", "wait")
Kevin Enderby31cc9652010-05-28 21:20:21 +0000695 .Case("movzx", "movzb")
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000696 .Default(Name);
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000697
698 // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
699 const MCExpr *ExtraImmOp = 0;
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000700 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000701 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
702 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000703 bool IsVCMP = PatchedName.startswith("vcmp");
704 unsigned SSECCIdx = IsVCMP ? 4 : 3;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000705 unsigned SSEComparisonCode = StringSwitch<unsigned>(
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000706 PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
Bruno Cardoso Lopescc69e132010-07-07 22:24:03 +0000707 .Case("eq", 0)
708 .Case("lt", 1)
709 .Case("le", 2)
710 .Case("unord", 3)
711 .Case("neq", 4)
712 .Case("nlt", 5)
713 .Case("nle", 6)
714 .Case("ord", 7)
715 .Case("eq_uq", 8)
716 .Case("nge", 9)
717 .Case("ngt", 0x0A)
718 .Case("false", 0x0B)
719 .Case("neq_oq", 0x0C)
720 .Case("ge", 0x0D)
721 .Case("gt", 0x0E)
722 .Case("true", 0x0F)
723 .Case("eq_os", 0x10)
724 .Case("lt_oq", 0x11)
725 .Case("le_oq", 0x12)
726 .Case("unord_s", 0x13)
727 .Case("neq_us", 0x14)
728 .Case("nlt_uq", 0x15)
729 .Case("nle_uq", 0x16)
730 .Case("ord_s", 0x17)
731 .Case("eq_us", 0x18)
732 .Case("nge_uq", 0x19)
733 .Case("ngt_uq", 0x1A)
734 .Case("false_os", 0x1B)
735 .Case("neq_os", 0x1C)
736 .Case("ge_oq", 0x1D)
737 .Case("gt_oq", 0x1E)
738 .Case("true_us", 0x1F)
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000739 .Default(~0U);
740 if (SSEComparisonCode != ~0U) {
741 ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode,
742 getParser().getContext());
743 if (PatchedName.endswith("ss")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000744 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000745 } else if (PatchedName.endswith("sd")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000746 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000747 } else if (PatchedName.endswith("ps")) {
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000748 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000749 } else {
750 assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
Bruno Cardoso Lopes428256b2010-06-23 21:10:57 +0000751 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000752 }
753 }
754 }
Daniel Dunbar1b6c0602010-02-10 21:19:28 +0000755 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000756
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000757 if (ExtraImmOp)
758 Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
759
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000760 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000761
762 // Parse '*' modifier.
763 if (getLexer().is(AsmToken::Star)) {
Sean Callanan18b83232010-01-19 21:44:56 +0000764 SMLoc Loc = Parser.getTok().getLoc();
Chris Lattnerb4307b32010-01-15 19:28:38 +0000765 Operands.push_back(X86Operand::CreateToken("*", Loc));
Sean Callananb9a25b72010-01-19 20:27:46 +0000766 Parser.Lex(); // Eat the star.
Daniel Dunbar0db68f42009-08-11 05:00:25 +0000767 }
768
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000769 // Read the first operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000770 if (X86Operand *Op = ParseOperand())
771 Operands.push_back(Op);
772 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000773 return true;
Daniel Dunbar39e2dd72010-05-25 19:49:32 +0000774
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000775 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +0000776 Parser.Lex(); // Eat the comma.
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000777
778 // Parse and remember the operand.
Chris Lattner309264d2010-01-15 18:44:13 +0000779 if (X86Operand *Op = ParseOperand())
780 Operands.push_back(Op);
781 else
Daniel Dunbar16cdcb32009-07-28 22:40:46 +0000782 return true;
783 }
784 }
785
Daniel Dunbard5e77052010-03-13 00:47:29 +0000786 // FIXME: Hack to handle recognizing s{hr,ar,hl}? $1.
787 if ((Name.startswith("shr") || Name.startswith("sar") ||
788 Name.startswith("shl")) &&
789 Operands.size() == 3 &&
790 static_cast<X86Operand*>(Operands[1])->isImm() &&
791 isa<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm()) &&
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000792 cast<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm())->getValue() == 1) {
793 delete Operands[1];
Daniel Dunbard5e77052010-03-13 00:47:29 +0000794 Operands.erase(Operands.begin() + 1);
Daniel Dunbarf2de13f2010-03-20 22:36:38 +0000795 }
Daniel Dunbard5e77052010-03-13 00:47:29 +0000796
Kevin Enderbycf50a532010-05-25 20:52:34 +0000797 // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
798 // "f{mul*,add*,sub*,div*} $op"
799 if ((Name.startswith("fmul") || Name.startswith("fadd") ||
800 Name.startswith("fsub") || Name.startswith("fdiv")) &&
801 Operands.size() == 3 &&
802 static_cast<X86Operand*>(Operands[2])->isReg() &&
803 static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
804 delete Operands[2];
805 Operands.erase(Operands.begin() + 2);
806 }
807
Chris Lattner98986712010-01-14 22:21:20 +0000808 return false;
Daniel Dunbara3af3702009-07-20 18:55:04 +0000809}
810
Kevin Enderby9c656452009-09-10 20:51:44 +0000811bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
812 StringRef IDVal = DirectiveID.getIdentifier();
813 if (IDVal == ".word")
814 return ParseDirectiveWord(2, DirectiveID.getLoc());
815 return true;
816}
817
818/// ParseDirectiveWord
819/// ::= .word [ expression (, expression)* ]
820bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
821 if (getLexer().isNot(AsmToken::EndOfStatement)) {
822 for (;;) {
823 const MCExpr *Value;
824 if (getParser().ParseExpression(Value))
825 return true;
826
Chris Lattneraaec2052010-01-19 19:46:13 +0000827 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
Kevin Enderby9c656452009-09-10 20:51:44 +0000828
829 if (getLexer().is(AsmToken::EndOfStatement))
830 break;
831
832 // FIXME: Improve diagnostic.
833 if (getLexer().isNot(AsmToken::Comma))
834 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +0000835 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000836 }
837 }
838
Sean Callananb9a25b72010-01-19 20:27:46 +0000839 Parser.Lex();
Kevin Enderby9c656452009-09-10 20:51:44 +0000840 return false;
841}
842
Chris Lattnerb5505d02010-05-13 00:02:47 +0000843/// LowerMOffset - Lower an 'moffset' form of an instruction, which just has a
844/// imm operand, to having "rm" or "mr" operands with the offset in the disp
845/// field.
846static void LowerMOffset(MCInst &Inst, unsigned Opc, unsigned RegNo,
847 bool isMR) {
848 MCOperand Disp = Inst.getOperand(0);
849
850 // Start over with an empty instruction.
851 Inst = MCInst();
852 Inst.setOpcode(Opc);
853
854 if (!isMR)
855 Inst.addOperand(MCOperand::CreateReg(RegNo));
856
857 // Add the mem operand.
858 Inst.addOperand(MCOperand::CreateReg(0)); // Segment
859 Inst.addOperand(MCOperand::CreateImm(1)); // Scale
860 Inst.addOperand(MCOperand::CreateReg(0)); // IndexReg
861 Inst.addOperand(Disp); // Displacement
862 Inst.addOperand(MCOperand::CreateReg(0)); // BaseReg
863
864 if (isMR)
865 Inst.addOperand(MCOperand::CreateReg(RegNo));
866}
867
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000868// FIXME: Custom X86 cleanup function to implement a temporary hack to handle
869// matching INCL/DECL correctly for x86_64. This needs to be replaced by a
870// proper mechanism for supporting (ambiguous) feature dependent instructions.
871void X86ATTAsmParser::InstructionCleanup(MCInst &Inst) {
872 if (!Is64Bit) return;
873
874 switch (Inst.getOpcode()) {
875 case X86::DEC16r: Inst.setOpcode(X86::DEC64_16r); break;
876 case X86::DEC16m: Inst.setOpcode(X86::DEC64_16m); break;
877 case X86::DEC32r: Inst.setOpcode(X86::DEC64_32r); break;
878 case X86::DEC32m: Inst.setOpcode(X86::DEC64_32m); break;
879 case X86::INC16r: Inst.setOpcode(X86::INC64_16r); break;
880 case X86::INC16m: Inst.setOpcode(X86::INC64_16m); break;
881 case X86::INC32r: Inst.setOpcode(X86::INC64_32r); break;
882 case X86::INC32m: Inst.setOpcode(X86::INC64_32m); break;
Chris Lattnerb5505d02010-05-13 00:02:47 +0000883
884 // moffset instructions are x86-32 only.
885 case X86::MOV8o8a: LowerMOffset(Inst, X86::MOV8rm , X86::AL , false); break;
886 case X86::MOV16o16a: LowerMOffset(Inst, X86::MOV16rm, X86::AX , false); break;
887 case X86::MOV32o32a: LowerMOffset(Inst, X86::MOV32rm, X86::EAX, false); break;
888 case X86::MOV8ao8: LowerMOffset(Inst, X86::MOV8mr , X86::AL , true); break;
889 case X86::MOV16ao16: LowerMOffset(Inst, X86::MOV16mr, X86::AX , true); break;
890 case X86::MOV32ao32: LowerMOffset(Inst, X86::MOV32mr, X86::EAX, true); break;
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000891 }
892}
893
Daniel Dunbarc918d602010-05-04 16:12:42 +0000894bool
895X86ATTAsmParser::MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*>
896 &Operands,
897 MCInst &Inst) {
898 // First, try a direct match.
899 if (!MatchInstructionImpl(Operands, Inst))
900 return false;
901
902 // Ignore anything which is obviously not a suffix match.
903 if (Operands.size() == 0)
904 return true;
905 X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
906 if (!Op->isToken() || Op->getToken().size() > 15)
907 return true;
908
909 // FIXME: Ideally, we would only attempt suffix matches for things which are
910 // valid prefixes, and we could just infer the right unambiguous
911 // type. However, that requires substantially more matcher support than the
912 // following hack.
913
914 // Change the operand to point to a temporary token.
915 char Tmp[16];
916 StringRef Base = Op->getToken();
917 memcpy(Tmp, Base.data(), Base.size());
918 Op->setTokenValue(StringRef(Tmp, Base.size() + 1));
919
920 // Check for the various suffix matches.
921 Tmp[Base.size()] = 'b';
922 bool MatchB = MatchInstructionImpl(Operands, Inst);
923 Tmp[Base.size()] = 'w';
924 bool MatchW = MatchInstructionImpl(Operands, Inst);
925 Tmp[Base.size()] = 'l';
926 bool MatchL = MatchInstructionImpl(Operands, Inst);
Daniel Dunbar04814492010-05-12 00:54:20 +0000927 Tmp[Base.size()] = 'q';
928 bool MatchQ = MatchInstructionImpl(Operands, Inst);
Daniel Dunbarc918d602010-05-04 16:12:42 +0000929
930 // Restore the old token.
931 Op->setTokenValue(Base);
932
933 // If exactly one matched, then we treat that as a successful match (and the
934 // instruction will already have been filled in correctly, since the failing
935 // matches won't have modified it).
Daniel Dunbar04814492010-05-12 00:54:20 +0000936 if (MatchB + MatchW + MatchL + MatchQ == 3)
Daniel Dunbarc918d602010-05-04 16:12:42 +0000937 return false;
938
Daniel Dunbarc918d602010-05-04 16:12:42 +0000939 // Otherwise, the match failed.
940 return true;
941}
942
943
Sean Callanane88f5522010-01-23 02:43:15 +0000944extern "C" void LLVMInitializeX86AsmLexer();
945
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000946// Force static initialization.
947extern "C" void LLVMInitializeX86AsmParser() {
Daniel Dunbarf98bc632010-03-18 20:06:02 +0000948 RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
949 RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
Sean Callanane88f5522010-01-23 02:43:15 +0000950 LLVMInitializeX86AsmLexer();
Daniel Dunbar092a9dd2009-07-17 20:42:00 +0000951}
Daniel Dunbar0e2771f2009-07-29 00:02:19 +0000952
953#include "X86GenAsmMatcher.inc"