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