blob: a1866186d7e06fa528460812ca165d675bfb18cb [file] [log] [blame]
Chris Lattnere6c561b2009-06-23 18:41:30 +00001//===- MC-X86Specific.cpp - X86-Specific code for MC ----------------------===//
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//
10// This file implements X86-specific parsing, encoding and decoding stuff for
11// MC.
12//
13//===----------------------------------------------------------------------===//
14
15#include "AsmParser.h"
16#include "llvm/MC/MCInst.h"
17using namespace llvm;
18
19/// X86Operand - Instances of this class represent one X86 machine instruction.
20struct AsmParser::X86Operand {
21 enum {
22 Register,
23 Immediate,
24 Memory
25 } Kind;
26
27 union {
28 struct {
29 unsigned RegNo;
30 } Reg;
31
32 struct {
Daniel Dunbar4967dbd2009-06-30 23:02:44 +000033 MCValue Val;
Chris Lattnere6c561b2009-06-23 18:41:30 +000034 } Imm;
35
36 struct {
37 unsigned SegReg;
Daniel Dunbar4967dbd2009-06-30 23:02:44 +000038 MCValue Disp;
Chris Lattnere6c561b2009-06-23 18:41:30 +000039 unsigned BaseReg;
Daniel Dunbar3aafe4d2009-07-02 00:51:52 +000040 unsigned IndexReg;
Chris Lattnere6c561b2009-06-23 18:41:30 +000041 unsigned Scale;
Chris Lattnere6c561b2009-06-23 18:41:30 +000042 } Mem;
43 };
44
Daniel Dunbarb336eac2009-07-02 01:58:24 +000045 unsigned getReg() const {
46 assert(Kind == Register && "Invalid access!");
47 return Reg.RegNo;
48 }
49
Chris Lattnere6c561b2009-06-23 18:41:30 +000050 static X86Operand CreateReg(unsigned RegNo) {
51 X86Operand Res;
52 Res.Kind = Register;
53 Res.Reg.RegNo = RegNo;
54 return Res;
55 }
Daniel Dunbar4967dbd2009-06-30 23:02:44 +000056 static X86Operand CreateImm(MCValue Val) {
Chris Lattnere6c561b2009-06-23 18:41:30 +000057 X86Operand Res;
58 Res.Kind = Immediate;
59 Res.Imm.Val = Val;
60 return Res;
61 }
Daniel Dunbar4967dbd2009-06-30 23:02:44 +000062 static X86Operand CreateMem(unsigned SegReg, MCValue Disp, unsigned BaseReg,
Daniel Dunbar3aafe4d2009-07-02 00:51:52 +000063 unsigned IndexReg, unsigned Scale) {
Daniel Dunbarb336eac2009-07-02 01:58:24 +000064 // If there is no index register, we should never have a scale, and we
65 // should always have a scale (in {1,2,4,8}) if we do.
66 assert(((Scale == 0 && !IndexReg) ||
67 (IndexReg && (Scale == 1 || Scale == 2 ||
68 Scale == 4 || Scale == 8))) &&
69 "Invalid scale!");
Chris Lattnere6c561b2009-06-23 18:41:30 +000070 X86Operand Res;
71 Res.Kind = Memory;
72 Res.Mem.SegReg = SegReg;
73 Res.Mem.Disp = Disp;
74 Res.Mem.BaseReg = BaseReg;
Daniel Dunbar3aafe4d2009-07-02 00:51:52 +000075 Res.Mem.IndexReg = IndexReg;
Chris Lattnere6c561b2009-06-23 18:41:30 +000076 Res.Mem.Scale = Scale;
Chris Lattnere6c561b2009-06-23 18:41:30 +000077 return Res;
78 }
Chris Lattnere6c561b2009-06-23 18:41:30 +000079};
80
Daniel Dunbarb336eac2009-07-02 01:58:24 +000081bool AsmParser::ParseX86Register(X86Operand &Op) {
82 assert(Lexer.getKind() == asmtok::Register && "Invalid token kind!");
83
84 // FIXME: Decode register number.
85 Op = X86Operand::CreateReg(123);
86 Lexer.Lex(); // Eat register token.
87
88 return false;
89}
90
Chris Lattnere6c561b2009-06-23 18:41:30 +000091bool AsmParser::ParseX86Operand(X86Operand &Op) {
92 switch (Lexer.getKind()) {
93 default:
94 return ParseX86MemOperand(Op);
95 case asmtok::Register:
Chris Lattnere6c561b2009-06-23 18:41:30 +000096 // FIXME: if a segment register, this could either be just the seg reg, or
97 // the start of a memory operand.
Daniel Dunbarb336eac2009-07-02 01:58:24 +000098 return ParseX86Register(Op);
Chris Lattnere6c561b2009-06-23 18:41:30 +000099 case asmtok::Dollar: {
100 // $42 -> immediate.
101 Lexer.Lex();
Daniel Dunbar4967dbd2009-06-30 23:02:44 +0000102 MCValue Val;
103 if (ParseRelocatableExpression(Val))
104 return true;
105 Op = X86Operand::CreateImm(Val);
Chris Lattnere6c561b2009-06-23 18:41:30 +0000106 return false;
Daniel Dunbar4967dbd2009-06-30 23:02:44 +0000107 }
108 case asmtok::Star: {
Chris Lattnere6c561b2009-06-23 18:41:30 +0000109 Lexer.Lex(); // Eat the star.
110
111 if (Lexer.is(asmtok::Register)) {
Daniel Dunbarb336eac2009-07-02 01:58:24 +0000112 if (ParseX86Register(Op))
113 return true;
Chris Lattnere6c561b2009-06-23 18:41:30 +0000114 } else if (ParseX86MemOperand(Op))
115 return true;
116
Daniel Dunbarb336eac2009-07-02 01:58:24 +0000117 // FIXME: Note the '*' in the operand for use by the matcher.
Chris Lattnere6c561b2009-06-23 18:41:30 +0000118 return false;
119 }
120 }
121}
122
123/// ParseX86MemOperand: segment: disp(basereg, indexreg, scale)
124bool AsmParser::ParseX86MemOperand(X86Operand &Op) {
125 // FIXME: If SegReg ':' (e.g. %gs:), eat and remember.
126 unsigned SegReg = 0;
127
128 // We have to disambiguate a parenthesized expression "(4+5)" from the start
129 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
130 // only way to do this without lookahead is to eat the ( and see what is after
131 // it.
Daniel Dunbar4967dbd2009-06-30 23:02:44 +0000132 MCValue Disp = MCValue::get(0, 0, 0);
Chris Lattnere6c561b2009-06-23 18:41:30 +0000133 if (Lexer.isNot(asmtok::LParen)) {
Daniel Dunbar4967dbd2009-06-30 23:02:44 +0000134 if (ParseRelocatableExpression(Disp)) return true;
Chris Lattnere6c561b2009-06-23 18:41:30 +0000135
136 // After parsing the base expression we could either have a parenthesized
137 // memory address or not. If not, return now. If so, eat the (.
138 if (Lexer.isNot(asmtok::LParen)) {
139 Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 0);
140 return false;
141 }
142
143 // Eat the '('.
144 Lexer.Lex();
145 } else {
146 // Okay, we have a '('. We don't know if this is an expression or not, but
147 // so we have to eat the ( to see beyond it.
148 Lexer.Lex(); // Eat the '('.
149
150 if (Lexer.is(asmtok::Register) || Lexer.is(asmtok::Comma)) {
151 // Nothing to do here, fall into the code below with the '(' part of the
152 // memory operand consumed.
153 } else {
154 // It must be an parenthesized expression, parse it now.
Daniel Dunbar5ebef272009-07-02 02:09:07 +0000155 if (ParseParenRelocatableExpression(Disp))
Chris Lattnere6c561b2009-06-23 18:41:30 +0000156 return true;
157
158 // After parsing the base expression we could either have a parenthesized
159 // memory address or not. If not, return now. If so, eat the (.
160 if (Lexer.isNot(asmtok::LParen)) {
161 Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 0);
162 return false;
163 }
164
165 // Eat the '('.
166 Lexer.Lex();
167 }
168 }
169
170 // If we reached here, then we just ate the ( of the memory operand. Process
171 // the rest of the memory operand.
Daniel Dunbar3aafe4d2009-07-02 00:51:52 +0000172 unsigned BaseReg = 0, IndexReg = 0, Scale = 0;
Chris Lattnere6c561b2009-06-23 18:41:30 +0000173
174 if (Lexer.is(asmtok::Register)) {
Daniel Dunbarb336eac2009-07-02 01:58:24 +0000175 if (ParseX86Register(Op))
176 return true;
177 BaseReg = Op.getReg();
Chris Lattnere6c561b2009-06-23 18:41:30 +0000178 }
179
180 if (Lexer.is(asmtok::Comma)) {
181 Lexer.Lex(); // eat the comma.
182
183 if (Lexer.is(asmtok::Register)) {
Daniel Dunbarb336eac2009-07-02 01:58:24 +0000184 if (ParseX86Register(Op))
185 return true;
186 IndexReg = Op.getReg();
Chris Lattnere6c561b2009-06-23 18:41:30 +0000187 Scale = 1; // If not specified, the scale defaults to 1.
188 }
189
190 if (Lexer.is(asmtok::Comma)) {
Daniel Dunbarb336eac2009-07-02 01:58:24 +0000191 Lexer.Lex(); // Eat the comma.
Chris Lattnere6c561b2009-06-23 18:41:30 +0000192
193 // If present, get and validate scale amount.
194 if (Lexer.is(asmtok::IntVal)) {
195 int64_t ScaleVal = Lexer.getCurIntVal();
196 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8)
197 return TokError("scale factor in address must be 1, 2, 4 or 8");
198 Lexer.Lex(); // eat the scale.
199 Scale = (unsigned)ScaleVal;
200 }
201 }
202 }
203
204 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
205 if (Lexer.isNot(asmtok::RParen))
206 return TokError("unexpected token in memory operand");
207 Lexer.Lex(); // Eat the ')'.
208
Daniel Dunbar3aafe4d2009-07-02 00:51:52 +0000209 Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale);
Chris Lattnere6c561b2009-06-23 18:41:30 +0000210 return false;
211}
212
Daniel Dunbard1d1e832009-06-30 23:38:38 +0000213/// MatchX86Inst - Convert a parsed instruction name and operand list into a
214/// concrete instruction.
215static bool MatchX86Inst(const char *Name,
216 llvm::SmallVector<AsmParser::X86Operand, 3> &Operands,
217 MCInst &Inst) {
218 return false;
219}
220
Chris Lattnere6c561b2009-06-23 18:41:30 +0000221/// ParseX86InstOperands - Parse the operands of an X86 instruction and return
222/// them as the operands of an MCInst.
Daniel Dunbard1d1e832009-06-30 23:38:38 +0000223bool AsmParser::ParseX86InstOperands(const char *InstName, MCInst &Inst) {
224 llvm::SmallVector<X86Operand, 3> Operands;
Chris Lattnere6c561b2009-06-23 18:41:30 +0000225
Daniel Dunbard1d1e832009-06-30 23:38:38 +0000226 if (Lexer.isNot(asmtok::EndOfStatement)) {
227 // Read the first operand.
228 Operands.push_back(X86Operand());
229 if (ParseX86Operand(Operands.back()))
Chris Lattnere6c561b2009-06-23 18:41:30 +0000230 return true;
Daniel Dunbard1d1e832009-06-30 23:38:38 +0000231
232 while (Lexer.is(asmtok::Comma)) {
233 Lexer.Lex(); // Eat the comma.
234
235 // Parse and remember the operand.
236 Operands.push_back(X86Operand());
237 if (ParseX86Operand(Operands.back()))
238 return true;
239 }
Chris Lattnere6c561b2009-06-23 18:41:30 +0000240 }
Daniel Dunbard1d1e832009-06-30 23:38:38 +0000241
242 return MatchX86Inst(InstName, Operands, Inst);
Chris Lattnere6c561b2009-06-23 18:41:30 +0000243}