blob: c33678cb262c1ee25cbf1b28e2255c00a0a22d0e [file] [log] [blame]
Daniel Dunbar71475772009-07-17 20:42:00 +00001//===-- X86AsmParser.cpp - Parse X86 assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattnerf29c0b62010-01-14 22:21:20 +000010#include "llvm/Target/TargetAsmParser.h"
Daniel Dunbar67038c12009-07-18 23:03:22 +000011#include "X86.h"
Daniel Dunbareefe8612010-07-19 05:44:09 +000012#include "X86Subtarget.h"
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +000013#include "llvm/ADT/SmallVector.h"
Daniel Dunbar3e0c9792010-02-10 21:19:28 +000014#include "llvm/ADT/StringSwitch.h"
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000015#include "llvm/ADT/Twine.h"
Kevin Enderbyce4bec82009-09-10 20:51:44 +000016#include "llvm/MC/MCStreamer.h"
Daniel Dunbar73da11e2009-08-31 08:08:38 +000017#include "llvm/MC/MCExpr.h"
Daniel Dunbarb6d6aa22009-07-31 02:32:59 +000018#include "llvm/MC/MCInst.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000019#include "llvm/MC/MCParser/MCAsmLexer.h"
20#include "llvm/MC/MCParser/MCAsmParser.h"
21#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000022#include "llvm/Support/SourceMgr.h"
Daniel Dunbar71475772009-07-17 20:42:00 +000023#include "llvm/Target/TargetRegistry.h"
24#include "llvm/Target/TargetAsmParser.h"
25using namespace llvm;
26
27namespace {
Benjamin Kramerb60210e2009-07-31 11:35:26 +000028struct X86Operand;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000029
30class X86ATTAsmParser : public TargetAsmParser {
31 MCAsmParser &Parser;
Daniel Dunbar419197c2010-07-19 00:33:49 +000032 TargetMachine &TM;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000033
Daniel Dunbar63ec0932010-03-18 20:06:02 +000034protected:
35 unsigned Is64Bit : 1;
36
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000037private:
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000038 MCAsmParser &getParser() const { return Parser; }
39
40 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
41
42 void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
43
44 bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
45
Chris Lattner0c2538f2010-01-15 18:51:29 +000046 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000047
Chris Lattnera2bbb7c2010-01-15 18:44:13 +000048 X86Operand *ParseOperand();
Chris Lattnerb9270732010-04-17 18:56:34 +000049 X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
Kevin Enderbyce4bec82009-09-10 20:51:44 +000050
51 bool ParseDirectiveWord(unsigned Size, SMLoc L);
52
Daniel Dunbar63ec0932010-03-18 20:06:02 +000053 void InstructionCleanup(MCInst &Inst);
54
Chris Lattnerf29c0b62010-01-14 22:21:20 +000055 bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Daniel Dunbare10787e2009-08-07 08:26:05 +000056 MCInst &Inst);
57
Daniel Dunbareefe8612010-07-19 05:44:09 +000058 /// @name Auto-generated Matcher Functions
59 /// {
60
61 unsigned ComputeAvailableFeatures(const X86Subtarget *Subtarget) const;
62
Daniel Dunbar9b816a12010-05-04 16:12:42 +000063 bool MatchInstructionImpl(
64 const SmallVectorImpl<MCParsedAsmOperand*> &Operands, MCInst &Inst);
65
Daniel Dunbar00331992009-07-29 00:02:19 +000066 /// }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000067
68public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000069 X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
Daniel Dunbareefe8612010-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 Dunbare1fdb0e2009-07-28 22:40:46 +000076
Benjamin Kramer92d89982010-07-14 22:38:02 +000077 virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattnerf29c0b62010-01-14 22:21:20 +000078 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Kevin Enderbyce4bec82009-09-10 20:51:44 +000079
80 virtual bool ParseDirective(AsmToken DirectiveID);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +000081};
Daniel Dunbar63ec0932010-03-18 20:06:02 +000082
83class X86_32ATTAsmParser : public X86ATTAsmParser {
84public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000085 X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
86 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbar63ec0932010-03-18 20:06:02 +000087 Is64Bit = false;
88 }
89};
90
91class X86_64ATTAsmParser : public X86ATTAsmParser {
92public:
Daniel Dunbar419197c2010-07-19 00:33:49 +000093 X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
94 : X86ATTAsmParser(T, _Parser, TM) {
Daniel Dunbar63ec0932010-03-18 20:06:02 +000095 Is64Bit = true;
96 }
97};
98
Chris Lattner4eb9df02009-07-29 06:33:53 +000099} // end anonymous namespace
100
Sean Callanan86c11812010-01-23 00:40:33 +0000101/// @name Auto-generated Match Functions
102/// {
103
Chris Lattner60db0a62010-02-09 00:34:28 +0000104static unsigned MatchRegisterName(StringRef Name);
Sean Callanan86c11812010-01-23 00:40:33 +0000105
106/// }
Chris Lattner4eb9df02009-07-29 06:33:53 +0000107
108namespace {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000109
110/// X86Operand - Instances of this class represent a parsed X86 machine
111/// instruction.
Chris Lattner872501b2010-01-14 21:20:55 +0000112struct X86Operand : public MCParsedAsmOperand {
Chris Lattner86e61532010-01-15 19:06:59 +0000113 enum KindTy {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000114 Token,
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000115 Register,
116 Immediate,
117 Memory
118 } Kind;
119
Chris Lattner0c2538f2010-01-15 18:51:29 +0000120 SMLoc StartLoc, EndLoc;
121
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000122 union {
123 struct {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000124 const char *Data;
125 unsigned Length;
126 } Tok;
127
128 struct {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000129 unsigned RegNo;
130 } Reg;
131
132 struct {
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000133 const MCExpr *Val;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000134 } Imm;
135
136 struct {
137 unsigned SegReg;
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000138 const MCExpr *Disp;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000139 unsigned BaseReg;
140 unsigned IndexReg;
141 unsigned Scale;
142 } Mem;
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +0000143 };
Daniel Dunbar71475772009-07-17 20:42:00 +0000144
Chris Lattner015cfb12010-01-15 19:33:43 +0000145 X86Operand(KindTy K, SMLoc Start, SMLoc End)
Chris Lattner86e61532010-01-15 19:06:59 +0000146 : Kind(K), StartLoc(Start), EndLoc(End) {}
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000147
Chris Lattner86e61532010-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 Dunbare10787e2009-08-07 08:26:05 +0000153 StringRef getToken() const {
154 assert(Kind == Token && "Invalid access!");
155 return StringRef(Tok.Data, Tok.Length);
156 }
Daniel Dunbar9b816a12010-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 Dunbare10787e2009-08-07 08:26:05 +0000162
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000163 unsigned getReg() const {
164 assert(Kind == Register && "Invalid access!");
165 return Reg.RegNo;
166 }
Daniel Dunbarf59ee962009-07-28 20:47:52 +0000167
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000168 const MCExpr *getImm() const {
Daniel Dunbar3ebf8482009-07-31 20:53:16 +0000169 assert(Kind == Immediate && "Invalid access!");
170 return Imm.Val;
171 }
172
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000173 const MCExpr *getMemDisp() const {
Daniel Dunbar3ebf8482009-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 Dunbar541efcc2009-08-08 07:50:56 +0000194 bool isToken() const {return Kind == Token; }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000195
196 bool isImm() const { return Kind == Immediate; }
197
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000198 bool isImmSExti16i8() const {
Daniel Dunbar8e33cb22009-08-09 07:20:21 +0000199 if (!isImm())
200 return false;
201
Daniel Dunbarb52fcd62010-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 Dunbar8e33cb22009-08-09 07:20:21 +0000207
Daniel Dunbarb52fcd62010-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 Dunbar8e33cb22009-08-09 07:20:21 +0000214 }
Daniel Dunbarb52fcd62010-05-22 21:02:33 +0000215 bool isImmSExti32i8() const {
Daniel Dunbar61655aa2010-05-20 20:20:39 +0000216 if (!isImm())
217 return false;
218
Daniel Dunbarb52fcd62010-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 Dunbar61655aa2010-05-20 20:20:39 +0000224
Daniel Dunbarb52fcd62010-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 Dunbar61655aa2010-05-20 20:20:39 +0000263 }
264
Daniel Dunbare10787e2009-08-07 08:26:05 +0000265 bool isMem() const { return Kind == Memory; }
266
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000267 bool isAbsMem() const {
268 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
Daniel Dunbar3184f222010-02-02 21:44:16 +0000269 !getMemIndexReg() && getMemScale() == 1;
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000270 }
271
Daniel Dunbara97adee2010-01-30 00:24:00 +0000272 bool isNoSegMem() const {
273 return Kind == Memory && !getMemSegReg();
274 }
275
Daniel Dunbare10787e2009-08-07 08:26:05 +0000276 bool isReg() const { return Kind == Register; }
277
Daniel Dunbar224340ca2010-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 Dunbaraeb1feb2009-08-10 21:00:45 +0000286 void addRegOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000287 assert(N == 1 && "Invalid number of operands!");
288 Inst.addOperand(MCOperand::CreateReg(getReg()));
289 }
290
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000291 void addImmOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbare10787e2009-08-07 08:26:05 +0000292 assert(N == 1 && "Invalid number of operands!");
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000293 addExpr(Inst, getImm());
Daniel Dunbare10787e2009-08-07 08:26:05 +0000294 }
295
Daniel Dunbaraeb1feb2009-08-10 21:00:45 +0000296 void addMemOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbara97adee2010-01-30 00:24:00 +0000297 assert((N == 5) && "Invalid number of operands!");
Daniel Dunbare10787e2009-08-07 08:26:05 +0000298 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
299 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
300 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000301 addExpr(Inst, getMemDisp());
Daniel Dunbara97adee2010-01-30 00:24:00 +0000302 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
303 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000304
Daniel Dunbar76e5d702010-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 Dunbara97adee2010-01-30 00:24:00 +0000310 void addNoSegMemOperands(MCInst &Inst, unsigned N) const {
311 assert((N == 4) && "Invalid number of operands!");
Daniel Dunbara97adee2010-01-30 00:24:00 +0000312 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
313 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
314 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
Daniel Dunbar224340ca2010-02-13 00:17:21 +0000315 addExpr(Inst, getMemDisp());
Daniel Dunbare10787e2009-08-07 08:26:05 +0000316 }
317
Chris Lattner528d00b2010-01-15 19:28:38 +0000318 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
319 X86Operand *Res = new X86Operand(Token, Loc, Loc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000320 Res->Tok.Data = Str.data();
321 Res->Tok.Length = Str.size();
Daniel Dunbare10787e2009-08-07 08:26:05 +0000322 return Res;
323 }
324
Chris Lattner0c2538f2010-01-15 18:51:29 +0000325 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
Chris Lattner86e61532010-01-15 19:06:59 +0000326 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
Chris Lattner0c2538f2010-01-15 18:51:29 +0000327 Res->Reg.RegNo = RegNo;
Chris Lattner0c2538f2010-01-15 18:51:29 +0000328 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000329 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000330
Chris Lattner528d00b2010-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 Lattner0c2538f2010-01-15 18:51:29 +0000333 Res->Imm.Val = Val;
334 return Res;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000335 }
Daniel Dunbare10787e2009-08-07 08:26:05 +0000336
Daniel Dunbar76e5d702010-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 Dunbar3184f222010-02-02 21:44:16 +0000345 Res->Mem.Scale = 1;
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000346 return Res;
347 }
348
349 /// Create a generalized memory operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000350 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
351 unsigned BaseReg, unsigned IndexReg,
Chris Lattner015cfb12010-01-15 19:33:43 +0000352 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000353 // We should never just have a displacement, that should be parsed as an
354 // absolute memory operand.
Daniel Dunbara4fc8d92009-07-31 22:22:54 +0000355 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
356
Daniel Dunbar3ebf8482009-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 Dunbare1fdb0e2009-07-28 22:40:46 +0000359 "Invalid scale!");
Chris Lattner015cfb12010-01-15 19:33:43 +0000360 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
Chris Lattner0c2538f2010-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 Dunbare1fdb0e2009-07-28 22:40:46 +0000367 }
368};
Daniel Dunbar3c2a8932009-07-20 18:55:04 +0000369
Chris Lattner4eb9df02009-07-29 06:33:53 +0000370} // end anonymous namespace.
Daniel Dunbarf59ee962009-07-28 20:47:52 +0000371
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000372
Chris Lattner0c2538f2010-01-15 18:51:29 +0000373bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
374 SMLoc &StartLoc, SMLoc &EndLoc) {
Chris Lattnercc2ad082010-01-15 18:27:19 +0000375 RegNo = 0;
Sean Callanan936b0d32010-01-19 21:44:56 +0000376 const AsmToken &TokPercent = Parser.getTok();
Kevin Enderby7d912182009-09-03 17:15:07 +0000377 assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
Chris Lattner0c2538f2010-01-15 18:51:29 +0000378 StartLoc = TokPercent.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000379 Parser.Lex(); // Eat percent token.
Kevin Enderby7d912182009-09-03 17:15:07 +0000380
Sean Callanan936b0d32010-01-19 21:44:56 +0000381 const AsmToken &Tok = Parser.getTok();
Kevin Enderbyc0edda32009-09-16 17:18:29 +0000382 if (Tok.isNot(AsmToken::Identifier))
383 return Error(Tok.getLoc(), "invalid register name");
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000384
Daniel Dunbar00331992009-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 Enderby7d912182009-09-03 17:15:07 +0000387 RegNo = MatchRegisterName(Tok.getString());
Chris Lattner60db0a62010-02-09 00:34:28 +0000388
Chris Lattnerd00faaa2010-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 Lattner80486622010-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 Dunbar66f4f542009-08-08 21:22:41 +0000446 if (RegNo == 0)
Daniel Dunbar00331992009-07-29 00:02:19 +0000447 return Error(Tok.getLoc(), "invalid register name");
448
Chris Lattner0c2538f2010-01-15 18:51:29 +0000449 EndLoc = Tok.getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000450 Parser.Lex(); // Eat identifier token.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000451 return false;
Daniel Dunbar71475772009-07-17 20:42:00 +0000452}
453
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000454X86Operand *X86ATTAsmParser::ParseOperand() {
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000455 switch (getLexer().getKind()) {
456 default:
Chris Lattnerb9270732010-04-17 18:56:34 +0000457 // Parse a memory operand with no segment register.
458 return ParseMemOperand(0, Parser.getTok().getLoc());
Chris Lattnercc2ad082010-01-15 18:27:19 +0000459 case AsmToken::Percent: {
Chris Lattnerb9270732010-04-17 18:56:34 +0000460 // Read the register.
Chris Lattnercc2ad082010-01-15 18:27:19 +0000461 unsigned RegNo;
Chris Lattner0c2538f2010-01-15 18:51:29 +0000462 SMLoc Start, End;
463 if (ParseRegister(RegNo, Start, End)) return 0;
Chris Lattnerb9270732010-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 Lattnercc2ad082010-01-15 18:27:19 +0000473 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000474 case AsmToken::Dollar: {
475 // $42 -> immediate.
Sean Callanan936b0d32010-01-19 21:44:56 +0000476 SMLoc Start = Parser.getTok().getLoc(), End;
Sean Callanana83fd7d2010-01-19 20:27:46 +0000477 Parser.Lex();
Daniel Dunbar73da11e2009-08-31 08:08:38 +0000478 const MCExpr *Val;
Chris Lattnere17df0b2010-01-15 19:39:23 +0000479 if (getParser().ParseExpression(Val, End))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000480 return 0;
Chris Lattner528d00b2010-01-15 19:28:38 +0000481 return X86Operand::CreateImm(Val, Start, End);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000482 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000483 }
Daniel Dunbar2b11c7d2009-07-20 20:01:54 +0000484}
485
Chris Lattnerb9270732010-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 Dunbare1fdb0e2009-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 Lattner807a3bc2010-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 Dunbar73da11e2009-08-31 08:08:38 +0000494 const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000495 if (getLexer().isNot(AsmToken::LParen)) {
Chris Lattnere17df0b2010-01-15 19:39:23 +0000496 SMLoc ExprEnd;
497 if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
Daniel Dunbare1fdb0e2009-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 Dunbara4fc8d92009-07-31 22:22:54 +0000502 // Unless we have a segment register, treat this as an immediate.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000503 if (SegReg == 0)
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000504 return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
Chris Lattner015cfb12010-01-15 19:33:43 +0000505 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000506 }
507
508 // Eat the '('.
Sean Callanana83fd7d2010-01-19 20:27:46 +0000509 Parser.Lex();
Daniel Dunbare1fdb0e2009-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 Callanan936b0d32010-01-19 21:44:56 +0000513 SMLoc LParenLoc = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000514 Parser.Lex(); // Eat the '('.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000515
Kevin Enderby7d912182009-09-03 17:15:07 +0000516 if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
Daniel Dunbare1fdb0e2009-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 Lattner528d00b2010-01-15 19:28:38 +0000520 SMLoc ExprEnd;
521
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000522 // It must be an parenthesized expression, parse it now.
Chris Lattner528d00b2010-01-15 19:28:38 +0000523 if (getParser().ParseParenExpression(Disp, ExprEnd))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000524 return 0;
Daniel Dunbare1fdb0e2009-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 Dunbara4fc8d92009-07-31 22:22:54 +0000529 // Unless we have a segment register, treat this as an immediate.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000530 if (SegReg == 0)
Daniel Dunbar76e5d702010-01-30 01:02:48 +0000531 return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
Chris Lattner015cfb12010-01-15 19:33:43 +0000532 return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000533 }
534
535 // Eat the '('.
Sean Callanana83fd7d2010-01-19 20:27:46 +0000536 Parser.Lex();
Daniel Dunbare1fdb0e2009-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 Dunbar3ebf8482009-07-31 20:53:16 +0000542 unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000543
Chris Lattner0c2538f2010-01-15 18:51:29 +0000544 if (getLexer().is(AsmToken::Percent)) {
545 SMLoc L;
546 if (ParseRegister(BaseReg, L, L)) return 0;
547 }
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000548
549 if (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +0000550 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-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 Enderby7d912182009-09-03 17:15:07 +0000558 if (getLexer().is(AsmToken::Percent)) {
Chris Lattner0c2538f2010-01-15 18:51:29 +0000559 SMLoc L;
560 if (ParseRegister(IndexReg, L, L)) return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000561
562 if (getLexer().isNot(AsmToken::RParen)) {
563 // Parse the scale amount:
564 // ::= ',' [scale-expression]
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000565 if (getLexer().isNot(AsmToken::Comma)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000566 Error(Parser.getTok().getLoc(),
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000567 "expected comma in scale expression");
568 return 0;
569 }
Sean Callanana83fd7d2010-01-19 20:27:46 +0000570 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000571
572 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000573 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000574
575 int64_t ScaleVal;
576 if (getParser().ParseAbsoluteExpression(ScaleVal))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000577 return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000578
579 // Validate the scale amount.
Chris Lattnera2bbb7c2010-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 Dunbare1fdb0e2009-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 Callanan936b0d32010-01-19 21:44:56 +0000590 SMLoc Loc = Parser.getTok().getLoc();
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000591
592 int64_t Value;
593 if (getParser().ParseAbsoluteExpression(Value))
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000594 return 0;
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000595
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000596 Error(Loc, "cannot have scale factor without index register");
597 return 0;
Daniel Dunbare1fdb0e2009-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 Lattnera2bbb7c2010-01-15 18:44:13 +0000602 if (getLexer().isNot(AsmToken::RParen)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000603 Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000604 return 0;
605 }
Sean Callanan936b0d32010-01-19 21:44:56 +0000606 SMLoc MemEnd = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +0000607 Parser.Lex(); // Eat the ')'.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000608
Chris Lattner015cfb12010-01-15 19:33:43 +0000609 return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
610 MemStart, MemEnd);
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000611}
612
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000613bool X86ATTAsmParser::
Benjamin Kramer92d89982010-07-14 22:38:02 +0000614ParseInstruction(StringRef Name, SMLoc NameLoc,
Chris Lattnerf29c0b62010-01-14 22:21:20 +0000615 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Dan Gohman29790ed2010-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 Enderby76a6b662010-07-13 20:05:41 +0000624 else if (Name == "pusha")
625 return Error(NameLoc, "pusha cannot be encoded in 64-bit mode");
Dan Gohman29790ed2010-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 Enderby0de0f3f2010-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 Dunbar3e0c9792010-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 Gohman29790ed2010-05-20 16:16:00 +0000655 .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
656 .Case("popf", Is64Bit ? "popfq" : "popfl")
Kevin Enderby7e7482c2010-05-21 23:01:38 +0000657 .Case("retl", Is64Bit ? "retl" : "ret")
658 .Case("retq", Is64Bit ? "ret" : "retq")
Daniel Dunbard459e292010-05-22 06:37:33 +0000659 .Case("setz", "sete")
660 .Case("setnz", "setne")
661 .Case("jz", "je")
662 .Case("jnz", "jne")
Kevin Enderby9738f642010-05-27 21:33:19 +0000663 .Case("jc", "jb")
Kevin Enderby0de0f3f2010-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 Enderby9738f642010-05-27 21:33:19 +0000667 .Case("jecxz", "jcxz")
Kevin Enderby0de0f3f2010-06-08 23:48:44 +0000668 .Case("jrcxz", "jcxz")
Kevin Enderby9738f642010-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 Enderbydc71cc72010-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 Enderbyb2922892010-05-28 20:59:10 +0000694 .Case("fwait", "wait")
Kevin Enderby4c71e082010-05-28 21:20:21 +0000695 .Case("movzx", "movzb")
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000696 .Default(Name);
Daniel Dunbar0e767d72010-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 Lopes3183dd52010-06-23 21:10:57 +0000700 if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000701 (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
702 PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000703 bool IsVCMP = PatchedName.startswith("vcmp");
704 unsigned SSECCIdx = IsVCMP ? 4 : 3;
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000705 unsigned SSEComparisonCode = StringSwitch<unsigned>(
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000706 PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
Bruno Cardoso Lopes6c614512010-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 Dunbar0e767d72010-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 Lopes3183dd52010-06-23 21:10:57 +0000744 PatchedName = IsVCMP ? "vcmpss" : "cmpss";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000745 } else if (PatchedName.endswith("sd")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000746 PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000747 } else if (PatchedName.endswith("ps")) {
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000748 PatchedName = IsVCMP ? "vcmpps" : "cmpps";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000749 } else {
750 assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
Bruno Cardoso Lopes3183dd52010-06-23 21:10:57 +0000751 PatchedName = IsVCMP ? "vcmppd" : "cmppd";
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000752 }
753 }
754 }
Daniel Dunbar3e0c9792010-02-10 21:19:28 +0000755 Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000756
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000757 if (ExtraImmOp)
758 Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
759
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000760 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Daniel Dunbar71527c12009-08-11 05:00:25 +0000761
762 // Parse '*' modifier.
763 if (getLexer().is(AsmToken::Star)) {
Sean Callanan936b0d32010-01-19 21:44:56 +0000764 SMLoc Loc = Parser.getTok().getLoc();
Chris Lattner528d00b2010-01-15 19:28:38 +0000765 Operands.push_back(X86Operand::CreateToken("*", Loc));
Sean Callanana83fd7d2010-01-19 20:27:46 +0000766 Parser.Lex(); // Eat the star.
Daniel Dunbar71527c12009-08-11 05:00:25 +0000767 }
768
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000769 // Read the first operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000770 if (X86Operand *Op = ParseOperand())
771 Operands.push_back(Op);
772 else
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000773 return true;
Daniel Dunbar0e767d72010-05-25 19:49:32 +0000774
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000775 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +0000776 Parser.Lex(); // Eat the comma.
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000777
778 // Parse and remember the operand.
Chris Lattnera2bbb7c2010-01-15 18:44:13 +0000779 if (X86Operand *Op = ParseOperand())
780 Operands.push_back(Op);
781 else
Daniel Dunbare1fdb0e2009-07-28 22:40:46 +0000782 return true;
783 }
784 }
785
Daniel Dunbar18fc3442010-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 Dunbarfbd12cc2010-03-20 22:36:38 +0000792 cast<MCConstantExpr>(static_cast<X86Operand*>(Operands[1])->getImm())->getValue() == 1) {
793 delete Operands[1];
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000794 Operands.erase(Operands.begin() + 1);
Daniel Dunbarfbd12cc2010-03-20 22:36:38 +0000795 }
Daniel Dunbar18fc3442010-03-13 00:47:29 +0000796
Kevin Enderby492d4f42010-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 Lattnerf29c0b62010-01-14 22:21:20 +0000808 return false;
Daniel Dunbar3c2a8932009-07-20 18:55:04 +0000809}
810
Kevin Enderbyce4bec82009-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 Lattnerc35681b2010-01-19 19:46:13 +0000827 getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
Kevin Enderbyce4bec82009-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 Callanana83fd7d2010-01-19 20:27:46 +0000835 Parser.Lex();
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000836 }
837 }
838
Sean Callanana83fd7d2010-01-19 20:27:46 +0000839 Parser.Lex();
Kevin Enderbyce4bec82009-09-10 20:51:44 +0000840 return false;
841}
842
Chris Lattner9efef002010-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 Dunbar63ec0932010-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 Lattner9efef002010-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 Dunbar63ec0932010-03-18 20:06:02 +0000891 }
892}
893
Daniel Dunbar9b816a12010-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 Dunbar059379a2010-05-12 00:54:20 +0000927 Tmp[Base.size()] = 'q';
928 bool MatchQ = MatchInstructionImpl(Operands, Inst);
Daniel Dunbar9b816a12010-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 Dunbar059379a2010-05-12 00:54:20 +0000936 if (MatchB + MatchW + MatchL + MatchQ == 3)
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000937 return false;
938
Daniel Dunbar9b816a12010-05-04 16:12:42 +0000939 // Otherwise, the match failed.
940 return true;
941}
942
943
Sean Callanan5051cb82010-01-23 02:43:15 +0000944extern "C" void LLVMInitializeX86AsmLexer();
945
Daniel Dunbar71475772009-07-17 20:42:00 +0000946// Force static initialization.
947extern "C" void LLVMInitializeX86AsmParser() {
Daniel Dunbar63ec0932010-03-18 20:06:02 +0000948 RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
949 RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
Sean Callanan5051cb82010-01-23 02:43:15 +0000950 LLVMInitializeX86AsmLexer();
Daniel Dunbar71475772009-07-17 20:42:00 +0000951}
Daniel Dunbar00331992009-07-29 00:02:19 +0000952
953#include "X86GenAsmMatcher.inc"