blob: 45774cf48c8b17d0791089d1978e871a6d56dc51 [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 {
33 // FIXME: Should be a general expression.
34 int64_t Val;
35 } Imm;
36
37 struct {
38 unsigned SegReg;
39 int64_t Disp; // FIXME: Should be a general expression.
40 unsigned BaseReg;
41 unsigned Scale;
42 unsigned ScaleReg;
43 } Mem;
44 };
45
46 static X86Operand CreateReg(unsigned RegNo) {
47 X86Operand Res;
48 Res.Kind = Register;
49 Res.Reg.RegNo = RegNo;
50 return Res;
51 }
52 static X86Operand CreateImm(int64_t Val) {
53 X86Operand Res;
54 Res.Kind = Immediate;
55 Res.Imm.Val = Val;
56 return Res;
57 }
58 static X86Operand CreateMem(unsigned SegReg, int64_t Disp, unsigned BaseReg,
59 unsigned Scale, unsigned ScaleReg) {
60 X86Operand Res;
61 Res.Kind = Memory;
62 Res.Mem.SegReg = SegReg;
63 Res.Mem.Disp = Disp;
64 Res.Mem.BaseReg = BaseReg;
65 Res.Mem.Scale = Scale;
66 Res.Mem.ScaleReg = ScaleReg;
67 return Res;
68 }
69
70 void AddToMCInst(MCInst &I) {
71 // FIXME: Add in x86 order here.
72 }
73};
74
75bool AsmParser::ParseX86Operand(X86Operand &Op) {
76 switch (Lexer.getKind()) {
77 default:
78 return ParseX86MemOperand(Op);
79 case asmtok::Register:
80 // FIXME: Decode reg #.
81 // FIXME: if a segment register, this could either be just the seg reg, or
82 // the start of a memory operand.
83 Op = X86Operand::CreateReg(123);
84 Lexer.Lex(); // Eat register.
85 return false;
86 case asmtok::Dollar: {
87 // $42 -> immediate.
88 Lexer.Lex();
89 int64_t Val;
90 if (ParseExpression(Val))
91 return TokError("expected integer constant");
92 Op = X86Operand::CreateReg(Val);
93 return false;
94 case asmtok::Star:
95 Lexer.Lex(); // Eat the star.
96
97 if (Lexer.is(asmtok::Register)) {
98 Op = X86Operand::CreateReg(123);
99 Lexer.Lex(); // Eat register.
100 } else if (ParseX86MemOperand(Op))
101 return true;
102
103 // FIXME: Note that these are 'dereferenced' so that clients know the '*' is
104 // there.
105 return false;
106 }
107 }
108}
109
110/// ParseX86MemOperand: segment: disp(basereg, indexreg, scale)
111bool AsmParser::ParseX86MemOperand(X86Operand &Op) {
112 // FIXME: If SegReg ':' (e.g. %gs:), eat and remember.
113 unsigned SegReg = 0;
114
115 // We have to disambiguate a parenthesized expression "(4+5)" from the start
116 // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
117 // only way to do this without lookahead is to eat the ( and see what is after
118 // it.
119 int64_t Disp = 0;
120 if (Lexer.isNot(asmtok::LParen)) {
121 if (ParseExpression(Disp)) return true;
122
123 // After parsing the base expression we could either have a parenthesized
124 // memory address or not. If not, return now. If so, eat the (.
125 if (Lexer.isNot(asmtok::LParen)) {
126 Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 0);
127 return false;
128 }
129
130 // Eat the '('.
131 Lexer.Lex();
132 } else {
133 // Okay, we have a '('. We don't know if this is an expression or not, but
134 // so we have to eat the ( to see beyond it.
135 Lexer.Lex(); // Eat the '('.
136
137 if (Lexer.is(asmtok::Register) || Lexer.is(asmtok::Comma)) {
138 // Nothing to do here, fall into the code below with the '(' part of the
139 // memory operand consumed.
140 } else {
141 // It must be an parenthesized expression, parse it now.
142 if (ParseParenExpr(Disp) ||
143 ParseBinOpRHS(1, Disp))
144 return true;
145
146 // After parsing the base expression we could either have a parenthesized
147 // memory address or not. If not, return now. If so, eat the (.
148 if (Lexer.isNot(asmtok::LParen)) {
149 Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 0);
150 return false;
151 }
152
153 // Eat the '('.
154 Lexer.Lex();
155 }
156 }
157
158 // If we reached here, then we just ate the ( of the memory operand. Process
159 // the rest of the memory operand.
160 unsigned BaseReg = 0, ScaleReg = 0, Scale = 0;
161
162 if (Lexer.is(asmtok::Register)) {
163 BaseReg = 123; // FIXME: decode reg #
164 Lexer.Lex(); // eat the register.
165 }
166
167 if (Lexer.is(asmtok::Comma)) {
168 Lexer.Lex(); // eat the comma.
169
170 if (Lexer.is(asmtok::Register)) {
171 ScaleReg = 123; // FIXME: decode reg #
172 Lexer.Lex(); // eat the register.
173 Scale = 1; // If not specified, the scale defaults to 1.
174 }
175
176 if (Lexer.is(asmtok::Comma)) {
177 Lexer.Lex(); // eat the comma.
178
179 // If present, get and validate scale amount.
180 if (Lexer.is(asmtok::IntVal)) {
181 int64_t ScaleVal = Lexer.getCurIntVal();
182 if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8)
183 return TokError("scale factor in address must be 1, 2, 4 or 8");
184 Lexer.Lex(); // eat the scale.
185 Scale = (unsigned)ScaleVal;
186 }
187 }
188 }
189
190 // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
191 if (Lexer.isNot(asmtok::RParen))
192 return TokError("unexpected token in memory operand");
193 Lexer.Lex(); // Eat the ')'.
194
195 Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, Scale, ScaleReg);
196 return false;
197}
198
199/// ParseX86InstOperands - Parse the operands of an X86 instruction and return
200/// them as the operands of an MCInst.
201bool AsmParser::ParseX86InstOperands(MCInst &Inst) {
202 // If no operands are present, just return.
203 if (Lexer.is(asmtok::EndOfStatement))
204 return false;
205
206 // Read the first operand.
207 X86Operand Op;
208 if (ParseX86Operand(Op))
209 return true;
210 Op.AddToMCInst(Inst);
211
212 while (Lexer.is(asmtok::Comma)) {
213 Lexer.Lex(); // Eat the comma.
214
215 // Parse and remember the operand.
216 Op = X86Operand();
217 if (ParseX86Operand(Op))
218 return true;
219 Op.AddToMCInst(Inst);
220 }
221 return false;
222}